[bzoj3744] Gty的妹子序列
还是分块>_<
强制在线求区间逆序。。如果没有空间限制的话显然是树套树?
分成根号n块,预处理出sum[i][j]表示从第i块的左端,到第j个点 这段区间内的逆序对个数。这部分可以直接树状数组O(n^1.5 logn)
那么对于每个询问,我们只要考虑左侧的零散节点对答案的贡献了。。
因此需要快速求出整块以及右侧零散节点插入后的树状数组。
再预处理出t[i][]表示前i块的数 的树状数组。。所以整块整块的树状数组就可以由前缀和得出。
再暴力插入右侧零散节点。。最后左侧零散节点就边插边统计了。。
总的时间复杂度O(n^1.5 logn)
块的大小就是根号n吧。。。不过具体来说比根号n小一些比较优
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=50003; 8 struct zs{ 9 int v;unsigned short pos; 10 }b[maxn];int cnt; 11 int id[maxn],mp[maxn],l[305],r[305]; 12 int sm[305][maxn],t[305][maxn],tt[maxn]; 13 int i,j,k,n,m,x,y,kuai,la; 14 15 int ra,fh;char rx; 16 inline int read(){ 17 rx=getchar(),fh=1,ra=0; 18 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 19 if(rx=='-')fh=-1,rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 21 } 22 23 bool cmp(zs a,zs b){return a.v<b.v;} 24 inline int query(int x,int y){ 25 register int j;int i,ans=0,k=id[y]-1; 26 if(x==l[id[x]])return sm[id[x]][y]; 27 if(id[x]==id[y]){ 28 for(i=x;i<=y;i++){ 29 for(j=mp[i],ans+=i-x;j;j-=j&-j)ans-=tt[j]; 30 for(j=mp[i];j<=cnt;j+=j&-j)++tt[j]; 31 } 32 for(i=x;i<=y;i++) 33 for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0; 34 return ans; 35 } 36 ans=sm[id[x]+1][y]; 37 for(i=y;i>=l[id[y]];i--)for(j=mp[i];j<=cnt;j+=j&-j)++tt[j]; 38 if(id[x]+1<id[y]) 39 for(i=r[id[x]];i>=x;i--){ 40 for(j=mp[i]-1;j;j-=j&-j)ans+=tt[j]+t[k][j]-t[id[x]][j]; 41 for(j=mp[i];j<=cnt;j+=j&-j)++tt[j]; 42 } 43 else{ 44 for(i=r[id[x]];i>=x;i--){ 45 for(j=mp[i]-1;j;j-=j&-j)ans+=tt[j]; 46 for(j=mp[i];j<=cnt;j+=j&-j)++tt[j]; 47 } 48 } 49 for(i=r[id[x]];i>=x;i--)for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0; 50 for(i=y;i>=l[id[y]];i--)for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0; 51 return ans; 52 } 53 int main(){ 54 n=read();kuai=min(n,166);//kuai=1; 55 for(i=1;i<=n;i++)b[i].v=read(),b[i].pos=i,id[i]=(i+kuai-1)/kuai; 56 57 for(i=1;i<=id[n];i++)l[i]=(i-1)*kuai+1,r[i]=i<id[n]?kuai*i:n; 58 sort(b+1,b+1+n,cmp); 59 for(i=1;i<=n;mp[b[i].pos]=cnt,i++) 60 if(b[i].v!=b[i-1].v||i==1)cnt++; 61 for(i=1;i<=id[n];i++){ 62 for(j=l[i];j<=r[i];j++)++t[i][mp[j]]; 63 for(j=1;j<=cnt;t[i][j]+=t[i-1][j],j++)if(j+(j&-j)<=cnt)t[i][j+(j&-j)]+=t[i][j]; 64 } 65 66 for(i=1;i<=id[n];i++){ 67 if(i>1)memset(tt,0,(cnt+1)<<2); 68 for(j=l[i];j<=n;j++){ 69 for(sm[i][j]=sm[i][j-1]+j-l[i],k=mp[j];k;k-=k&-k)sm[i][j]-=tt[k]; 70 for(k=mp[j];k<=cnt;k+=k&-k)++tt[k]; 71 } 72 }memset(tt,0,(cnt+1)<<2); 73 74 for(m=read();m;m--) 75 x=read()^la,y=read()^la, 76 la=query(x,y),printf("%d\n",la); 77 return 0; 78 }
一开始没删调试挂了两发= =我果然是傻逼QAQ