BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)

题面传送门

题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线

 

很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献,而这道题是用可持久化线段树罢了

首先对序列分块,设块大小为$S$

再建出主席树,我们就能在$O(logn)$时间内查询某个点$i$与区间$[l,r]$内的点产生的逆序对数量

然后处理出点和整块之间的答案,设$f(i,j)$表示第$i$个点与第$j$块的开始/末尾这段区间内的点产生的逆序对数量。

再根据 点到块的答案 统计出 块到块的答案

对于每次询问,利用预处理出的东西$O(1)$搞出 整块到整块 的贡献,再暴力枚举边角+主席树查询搞出 边角到整块 和 边角到边角 的贡献。

然后就会被卡常

我们可以用树状数组搞出 边角到边角 的贡献,再用预处理的信息搞出 边角对整块 的贡献...

虽然每次查询的时间也是$O(logn)$不变,但非递归的树状数组确实能减少大量的常数 #喷血

分析一下时间复杂度,预处理+查询=O(n\frac{n}{S}logn+QSlogn),因为预处理是用主席树查询的所以比较慢..块要开大一些

 

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 50500
  6 #define M1 120
  7 #define ll long long 
  8 #define uint unsigned int 
  9 using namespace std;
 10 
 11 template <typename _T> void read(_T &ret)
 12 {
 13     ret=0; _T fh=1; char c=getchar();
 14     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
 15     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
 16     ret=ret*fh;
 17 }
 18 
 19 struct SEG{
 20 int ls[N1*20],rs[N1*20],sz[N1*20],root[N1],tot;
 21 void pushup(int rt){ sz[rt]=sz[ls[rt]]+sz[rs[rt]];  }
 22 void upd(int x,int l,int r,int rt1,int &rt2,int w)
 23 {
 24     if(!rt2||rt1==rt2){ rt2=++tot; ls[rt2]=ls[rt1]; rs[rt2]=rs[rt1]; sz[rt2]=sz[rt1]; }
 25     if(l==r){ sz[rt2]+=w; return; }
 26     int mid=(l+r)>>1;
 27     if(x<=mid) upd(x,l,mid,ls[rt1],ls[rt2],w);
 28     else upd(x,mid+1,r,rs[rt1],rs[rt2],w);
 29     pushup(rt2);
 30 }
 31 int query(int L,int R,int l,int r,int rt1,int rt2)
 32 {
 33     if(L<=l&&r<=R) return sz[rt2]-sz[rt1];
 34     int mid=(l+r)>>1,ans=0;
 35     if(L<=mid) ans+=query(L,R,l,mid,ls[rt1],ls[rt2]);
 36     if(R>mid) ans+=query(L,R,mid+1,r,rs[rt1],rs[rt2]);
 37     return ans;
 38 }
 39 }s;
 40 
 41 
 42 int n,m,sq,Q,de;
 43 
 44 struct BIT{
 45 int sum[N1];
 46 int upd(int x,int w)
 47 {
 48     int i;
 49     for(i=x;i<=m;i+=(i&(-i)))
 50         sum[i]+=w;
 51 }
 52 int query(int x)
 53 {
 54     if(!x) return 0; int i,ans=0; 
 55     for(i=x;i>0;i-=(i&(-i)))
 56         ans+=sum[i];
 57     return ans;
 58 }
 59 }bit;
 60 
 61 int a[N1],b[N1],pie[N1],st[M1],ed[M1];
 62 uint f[N1][M1],g[M1][M1];
 63 
 64 int main()
 65 {
 66     int i,j,k,l,r,q,x,y,px,py; uint ans=0;
 67     scanf("%d",&n);
 68     for(i=1;i<=n;i++) read(a[i]), b[i]=a[i];
 69     sort(b+1,b+n+1); m=unique(b+1,b+n+1)-(b+1);
 70     for(i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
 71     for(i=1;i<=n;i++) s.upd(a[i],1,m,s.root[i-1],s.root[i],1);
 72     
 73     sq=450;
 74     for(i=1;i<=n;i++) pie[i]=(i-1)/sq+1, ed[pie[i]]=i;
 75     for(i=1;i<=pie[n];i++) st[i]=(i-1)*sq+1;
 76     for(i=1;i<=n;i++)
 77     {
 78         if(a[i]<m)
 79         {
 80             for(j=1;j<pie[i];j++)
 81                 f[i][j]=s.query(a[i]+1,m,1,m,s.root[st[j]-1],s.root[i-1]);
 82             f[i][0]=s.query(a[i]+1,m,1,m,s.root[st[pie[i]]-1],s.root[i-1]);
 83         }
 84         if(a[i]>1)
 85         {
 86             for(j=pie[i];j<=pie[n];j++)
 87             {
 88                 f[i][j]=s.query(1,a[i]-1,1,m,s.root[i],s.root[ed[j]]);
 89                 g[pie[i]][j]+=f[i][j];
 90             }
 91         }
 92     }
 93     for(j=1;j<=pie[n];j++)
 94     for(i=1;i+j<=pie[n];i++)
 95         g[i][i+j]+=g[i+1][i+j];
 96     
 97     scanf("%d",&Q);
 98     for(q=1;q<=Q;q++)
 99     {
100         read(x); read(y); x^=ans; y^=ans; ans=0; px=pie[x]; py=pie[y];
101         if(px!=py){
102             if(px+1<=py-1) ans=g[px+1][py-1];
103             for(i=x;i<=ed[px];i++) ans+=f[i][py-1];
104             if(px+1==py){ 
105                 for(i=st[py];i<=y;i++) ans+=f[i][0];
106             }else{ 
107                 for(i=st[py];i<=y;i++) ans+=f[i][px+1]; 
108             }
109             for(i=st[py];i<=y;i++) bit.upd(a[i],1);
110             for(i=x;i<=ed[px];i++) if(a[i]>1) ans+=bit.query(a[i]-1); 
111             for(i=st[py];i<=y;i++) bit.upd(a[i],-1);
112         }else{
113             for(i=y;i>=x;i--) 
114             {
115                 if(a[i]>1) ans+=bit.query(a[i]-1);
116                 bit.upd(a[i],1);
117             }
118             for(i=x;i<=y;i++) bit.upd(a[i],-1);
119         }
120         printf("%u\n",ans);
121     }
122     return 0;
123 }

 

posted @ 2019-03-26 21:10  guapisolo  阅读(205)  评论(0编辑  收藏  举报