【bzoj2821】作诗(Poetize)
2017-05-25 16:47
260 查看
分块做法*
ps:第一篇博客,有点小激动,有错误大佬别怼我;
题目大概是这样的;
类似于区间众数,在询问的区间中统计出现过偶数次的元素和。
那么这种类型的题目分块比暴力优越在哪??是的,只是因为预处理而已;
先用f[i][j]统计出:第i块 到 第j块中询问的答案;
对于不完整的块,我们最多做不超过块大小两倍,时间上有保证;
查询*
对于区间[a,b],可分为三个部分:1.[a,min(b,bl[a]*blo], 2.[bl[a]*blo+1,(bl[b-1]*blo], 3.[bl[b-1]*blo+1,b];
注意到第二部分的答案是已知的,那么影响结果的只能是1,3部分的元素;
每个暴力查询他在大区间中出现的次数,判断他在完整的块里是否被统计过,修改rtn;
应该就这些,另外对于查询他出现的次数,二分就行了,用vector记录这个元素所有出现的位置,看哪些在[a,b]中;
好了,代码如xia:
ps:第一篇博客,有点小激动,有错误大佬别怼我;
题目大概是这样的;
类似于区间众数,在询问的区间中统计出现过偶数次的元素和。
那么这种类型的题目分块比暴力优越在哪??是的,只是因为预处理而已;
先用f[i][j]统计出:第i块 到 第j块中询问的答案;
对于不完整的块,我们最多做不超过块大小两倍,时间上有保证;
查询*
对于区间[a,b],可分为三个部分:1.[a,min(b,bl[a]*blo], 2.[bl[a]*blo+1,(bl[b-1]*blo], 3.[bl[b-1]*blo+1,b];
注意到第二部分的答案是已知的,那么影响结果的只能是1,3部分的元素;
每个暴力查询他在大区间中出现的次数,判断他在完整的块里是否被统计过,修改rtn;
应该就这些,另外对于查询他出现的次数,二分就行了,用vector记录这个元素所有出现的位置,看哪些在[a,b]中;
好了,代码如xia:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> #include <map> #define LL long long using namespace std; int read(){ int rtn=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0')rtn=rtn*10+ch-'0',ch=getchar(); return rtn*f; } int n,q,c,id,lastans,m,v[100010],blo,flag[100010],cnt[100010],bl[100010],f[1505][1505]; vector<int>ve[100010];//不用vector写法复杂一些,蒟蒻不会; //如果按照sqrt(n/log(n)*log(2))分,块的数量比原来增多,; void reset(int x){ int l=(x-1)*blo+1,tot=0; for(int i=l;i<=n;i++)cnt[v[i]]=0; for(int i=l;i<=n;i++){ int t=bl[i]; cnt[v[i]]++; if(cnt[v[i]]==1){ f[x][t]=tot; continue; } if(!(cnt[v[i]]&1))tot++; if(cnt[v[i]]&1)tot--; f[x][t]=tot; //预处理,偶数加一,奇数减一,等于一的时候特判; } } int Query(int l,int r,int x){ return (upper_bound(ve[x].begin(),ve[x].end(),r)- lower_bound(ve[x].begin(),ve[x].end(),l)); } int query(int a,int b){ int ans=0,l=bl[a]*blo+1,r=(bl[b]-1)*blo; if(bl[a]==bl[b]||bl[a]+1==bl[b]){ for(int i=a;i<=b;i++){ if(flag[v[i]])continue; int t1=Query(a,b,v[i]); if(!(t1&1)){flag[v[i]]=1;ans++;} } for(int i=a;i<=b;i++)flag[v[i]]=0; } else{ ans=f[bl[a]+1][bl[b]-1]; for(int i=a;i<=bl[a]*blo;i++){ if(flag[v[i]])continue; int t1=Query(a,b,v[i]); int t2=Query(l,r,v[i]); if(!(t1&1)) if(t2&1||!t2)ans++; if(t1&1) if(!(t2&1)&&t2)ans--; flag[v[i]]=1; } for(int i=(bl[b]-1)*blo+1;i<=b;i++){ if(flag[v[i]])continue; int t1=Query(a,b,v[i]); int t2=Query(l,r,v[i]); if(!(t1&1)) if(t2&1||!t2)ans++; if(t1&1) if(!(t2&1)&&t2)ans--; flag[v[i]]=1; } for(int i=a;i<=bl[a]*blo;i++)flag[v[i]]=0; for(int i=(bl[b]-1)*blo+1;i<=b;i++)flag[v[i]]=0; } return ans; } int main() { n=read(),c=read(),q=read(); blo=sqrt((double)n/log((double)n)*log(2));//注意块大小 for(int i=1;i<=n;i++){ v[i]=read(); bl[i]=(i-1)/blo+1; ve[v[i]].push_back(i); } if(n%blo)m=n/blo+1; else m=n/blo; for(int i=1;i<=m;i++)reset(i); for(int i=1;i<=q;i++){ int x=read(),y=read(); x=(x+lastans)%n+1,y=(y+lastans)%n+1; if(x>y)swap(x,y); lastans=query(x,y); printf("%d\n",lastans); } return 0; }
相关文章推荐
- 【bzoj2821】作诗(Poetize) 分块
- bzoj2821[作诗(Poetize)]
- bzoj2821 作诗(Poetize)
- BZOJ 2821: 作诗(Poetize) | 分块
- BZOJ 2821 作诗(Poetize) 分块
- bzoj 2821: 作诗(Poetize)
- BZOJ 2821 作诗(Poetize) 分块
- bzoj 2821: 作诗(Poetize)【分块】
- BZOJ 2821 作诗(Poetize)(分块)
- 【分块】bzoj2821 作诗(Poetize)
- BZOJ2821: 作诗(Poetize)
- BZOJ 2821 作诗(Poetize)
- BZOJ 2821: 作诗(Poetize)|分块
- bzoj 2821: 作诗(Poetize) (分块)
- BZOJ2821 作诗(Poetize) 【分块】
- 分块-bzoj2821: 作诗(Poetize)
- 【BZOJ2821】作诗(Poetize) 分块
- [bzoj] 2821 作诗(Poetize) || 分块
- BZOJ_2821_作诗(Poetize)_分块
- [BZOJ 2821] 作诗(Poetize) 【分块】