[模拟赛] Order 树状数组(未解决)

Order

           给定3个1~n的排列a,b,c,若二元组(i,j)在a,b,c中都满足i在j的前面,称(i,j)相对顺序相同,问有多少二元组使得顺序相同。

【输入格式】

      第一行为一个正整数n

      接下来3行,每行n个数保证是一个排列

【输出格式】

一个非负整数表示有多少二元组使得相对顺序相同

【数据规模与约定】

对于1~3的测试点,n<=5000

对于4~7的测试点,n<=100000,保证第一个排列和第二个排列完全相同

对于8~9的测试点,n<=100000

对于10测试点,n<=1000000

from 学长 LYH

考试的时候只拿了70分。。。等看明白了再更。。。

70分: 30分暴力+40分垃圾前缀和。。(据说这40分要求逆序对??雾

#include<cstdio>
#include<iostream>
#include<algorithm>
#define R register int
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,top;
int posa[100010],posb[100010],posc[5010],stk[100010];
long long f[100010],c[100010];
bool lgl[5010][5010];
long long ans;
inline int lbt(int x) {return x&-x;}
inline void add(int pos) {
    for(;pos<=n;pos+=lbt(pos)) ++c[pos];
}
inline long long query(int pos) { register long long ret=0;
    for(;pos;pos-=lbt(pos)) ret+=c[pos]; return ret;
}
signed main() {
    freopen("order.in","r",stdin);
    freopen("order.out","w",stdout);
    n=g();
    if(n<=5000) {
//    if(0){
        for(R i=1;i<=n;++i) posa[g()]=i; 
        for(R i=1;i<=n;++i) posb[g()]=i;
        for(R i=1;i<=n;++i) posc[g()]=i;
        for(R i=1;i<=n;++i) for(R j=1;j<=n;++j) lgl[i][j]=(posa[i]<posa[j]);
        for(R i=1;i<=n;++i) for(R j=1;j<=n;++j) lgl[i][j]=lgl[i][j]&&(posb[i]<posb[j]);
        for(R i=1;i<=n;++i) for(R j=1;j<=n;++j) ans+=lgl[i][j]&&(posc[i]<posc[j]);
        printf("%lld\n",ans);
    } //else if(n<=100000) { 
//if(1){
//        for(R i=1;i<=n;++i) posa[g()]=i; for(R i=1;i<=n;++i) g();
//        for(R i=1;i<=n;++i) posb[i]=posa[g()];
//        for(R i=1;i<=n;++i) {
//            if(posb[i]>stk[top]) stk[++top]=posb[i];
//            else {
//                R pos=upper_bound(stk+1,stk+top+1,posb[i])-stk;
//                //cout<<pos<<endl;
//                stk[pos]=posb[i];
//            } 
//            //for(R j=1;j<=top;++j) cout<<stk[j]<<" "; cout<<endl;
//        } printf("%lld\n",(long long)top*(top-1));
//    }
    else if(n<=100000) {
        for(R i=1;i<=n;++i) posa[g()]=i; for(R i=1;i<=n;++i) g();
        for(R i=1;i<=n;++i) posb[i]=posa[g()];
        for(R i=1;i<=n;++i) f[i]=query(posb[i])+f[i-1],add(posb[i]); printf("%lld\n",f[n]);
    }
}
/*
20 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
10 8 2 4 19 16 7 12 9 3 5 1 11 14 15 18 17 6 20 13
*/

困死了。。。

2019.04.18

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10727233.html