bzoj 2821: 作诗(Poetize)【分块】
2018-01-05 21:22
204 查看
参考:http://hzwer.com/3663.html
除了麻烦一点也没什么难的,就是要注意细节。
首先\( O(n\sqrt{n}) \)时间下预处理出\( f[i][j] \),表示第\( i \)块和第\( j \)块之间的答案。\( L \)表示这个块的左端点,\( R \)表示这个块的右端点,\( v\)标记计算过程中已经被算到答案里的数字,\( bl \)表示这个节点属于第几个块,\( fr \)表示当前这个值最早出现的位置,\( la \)表示当前这个值最晚出现的位置。
询问的时候,当\( (l,r) \)处于同一个或者相邻两个快里,则直接暴力统计。否则把其完全跨越的块用\( f \) 查询,得到中间大块\( x-y \)的答案,考虑\( l-x \)和\( y-r \)对答案的影响,对于每个数统计它在\( x-y \)出现次数\( t1 \),以及\( l-r \)出现次数\( t2 \),根据\( t1 \),\( t2 \)的奇偶性考虑其对答案的影响。
对于清理数组要用\( for \),否则无法保证复杂度。
时间复杂度:\( O(n\sqrt{n}log_2n) \)
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=100005,K=1505,inf=1e9; int n,m,c,kuai,cnt,bl ,L ,R ,tmp ,f[K][K],fr ,la ,las,a ; bool v ; struct qwe { int p,v; }b ; bool cmp(const qwe &a,const qwe &b) { return (a.v<b.v)||(a.v==b.v&&a.p<b.p); } int read() { int r=0,f=1; char p=getchar(); while(p<'0'||p>'9') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } int up(int x,int v) { int l=fr[v],r=la[v],re=0; while(l<=r) { int mid=(l+r)>>1; if(x<b[mid].p) r=mid-1; else l=mid+1,re=mid; } return re; } int down(int x,int v) { int l=fr[v],r=la[v],re=inf; while(l<=r) { int mid=(l+r)>>1; if(x>b[mid].p) l=mid+1; else re=mid,r=mid-1; } return re; } int zhao(int x,int y,int v) { return max(up(y,v)-down(x,v)+1,0); } int ques(int x,int y) { int ans=0,t1,t2,a1,bx=bl[x],by=bl[y]; if(bx==by||bx+1==by) { for(int i=x;i<=y;i++) if(!v[a[i]]) { int t=zhao(x,y,a[i]); if(!(t&1)) { v[a[i]]=1; ans++; } } for(int i=x;i<=y;i++) v[a[i]]=0; } else { int l=L[bx+1],r=R[by-1]; ans=f[bx+1][by-1]; for(int i=x;i<l;i++) if(!v[a[i]]) { t1=zhao(x,y,a[i]),t2=zhao(l,r,a[i]); if(!(t1&1)) { if((t2&1)||!t2) ans++; } else if(!(t2&1)&&t2) ans--; v[a[i]]=1; } for(int i=r+1;i<=y;i++) if(!v[a[i]]) { t1=zhao(x,y,a[i]),t2=zhao(l,r,a[i]); if(!(t1&1)) { if((t2&1)||!t2) ans++; } else if(!(t2&1)&&t2) ans--; v[a[i]]=1; } for(int i=x;i<l;i++) v[a[i]]=0; for(int i=r+1;i<=y;i++) v[a[i]]=0; } return ans; } int main() { n=read(),c=read(),m=read();//cout<<n<<m<<c; for(int i=1;i<=n;i++) a[i]=read(); kuai=sqrt((double)n/log((double)n)*log(2)); if(n%kuai) cnt=n/kuai+1; else cnt=n/kuai; for(int i=1;i<=n;i++) bl[i]=(i-1)/kuai+1; for(int i=1;i<=cnt;i++) L[i]=(i-1)*kuai+1,R[i]=i*kuai; R[cnt]=n; int tot; for(int i=1;i<=cnt;i++) { for(int j=L[i];j<=n;j++) tmp[a[j]]=0; tot=0; for(int j=L[i];j<=n;j++) { if(!(tmp[a[j]]&1)&&tmp[a[j]])//注意当a[j]的个数为0的时候就不用减了 tot--; tmp[a[j]]++; if(!(tmp[a[j]]&1)) tot++; f[i][bl[j]]=tot; } } for(int i=1;i<=n;i++) b[i].p=i,b[i].v=a[i]; sort(b+1,b+n+1,cmp); for(int i=1;i<=n;i++) { if(!fr[b[i].v]) fr[b[i].v]=i; la[b[i].v]=i; } while(m--) { int l=read(),r=read(),x=(l+las)%n+1,y=(r+las)%n+1; if(x>y) swap(x,y); las=ques(x,y); printf("%d\n",las); } return 0; }
相关文章推荐
- BZOJ 2821 作诗(Poetize) 分块
- BZOJ 2821 作诗(Poetize) 分块
- BZOJ2821 作诗(Poetize) 【分块】
- 【分块】BZOJ2821 作诗(Poetize)
- BZOJ 2821: 作诗(Poetize) [分块]
- [bzoj] 2821 作诗(Poetize) || 分块
- 【BZOJ2821】作诗(Poetize) 分块
- BZOJ 2821: 作诗(Poetize)|分块
- BZOJ 2821 作诗(Poetize)(分块)
- bzoj 2821: 作诗(Poetize) 分块
- 分块-bzoj2821: 作诗(Poetize)
- BZOJ 2821: 作诗(Poetize)( 分块 )
- bzoj2821: 作诗(Poetize)【分块】
- BZOJ 2821 作诗(Poetize) 分块
- [BZOJ 2821] 作诗(Poetize) 【分块】
- 【bzoj2821】作诗(Poetize) 分块
- bzoj 2821: 作诗(Poetize) (分块)
- 【分块】bzoj2821 作诗(Poetize)
- BZOJ 2821 作诗(Poetize) 分块
- BZOJ2821: 作诗(Poetize)