[分块 随机Hash] Romanian IOI 2017 Selection #6 Jolteon
2017-07-01 22:41
260 查看
传送门
问有多少个区间,出现过的数出现次数都是奇数
给每个数随机一个hash值
然后区间中所有数的xor和 和 所有pre<l≤i≤r的数的异或和 相同
那么就合法
枚举右端点,新增一个数会对一段造成影响
变成区间异或,区间是否存在一个数,分块维护
问有多少个区间,出现过的数出现次数都是奇数
给每个数随机一个hash值
然后区间中所有数的xor和 和 所有pre<l≤i≤r的数的异或和 相同
那么就合法
枚举右端点,新增一个数会对一段造成影响
变成区间异或,区间是否存在一个数,分块维护
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef unsigned long long ull; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; const int BB=405; const int maxn=1000000; int last[maxn+5]; ull S[maxn+5]; int n,a ,pre ; int B,pos ,cnt,lp[BB],rp[BB],size[BB]; const int P=20007; ull H[BB][BB]; struct HashMap{ ull h[BB]; int cnt[BB],next[BB]; int head[P],vst[P],inum; int clk; void _new(){ ++clk; inum=0; } int &Head(int x){ return vst[x]!=clk?(vst[x]=clk,head[x]=0):head[x]; } int& operator[](ull x){ int hh=x%P; for (int p=Head(hh);p;p=next[p]) if (h[p]==x) return cnt[p]; int p=++inum; h[p]=x; cnt[p]=0; next[p]=head[hh]; head[hh]=p; return cnt[p]; } int find(ull x){ int hh=x%P; for (int p=Head(hh);p;p=next[p]) if (h[p]==x) return cnt[p]; return 0; } }Map[BB]; ull tag[BB]; inline void Build(int n){ B=(int)min(sqrt(n)+1,(double)n); for (int i=1;i<=n;i++) pos[i]=(i-1)/B+1; cnt=pos ; for (int i=1;i<=cnt;i++) lp[i]=(i-1)*B+1,rp[i]=i*B; rp[cnt]=n; for (int i=1;i<=cnt;i++) size[i]=rp[i]-lp[i]+1; ull sum=0; for (int i=1;i<=n;i++){ int b=pos[i]; H[b][i-lp[b]+1]=sum; Map[b][sum]++; sum^=S[a[i]]; } } inline void Add(int l,int r,ull t){ int lb=pos[l],rb=pos[r]; if (lb==rb){ Map[lb]._new(); for (int i=l-lp[lb]+1;i<=r-lp[lb]+1;i++) H[lb][i]^=t; for (int i=1;i<=size[lb];i++) Map[lb][H[lb][i]^=tag[lb]]++; tag[lb]=0; return; } for (int i=lb+1;i<rb;i++) tag[i]^=t; Map[lb]._new(); for (int i=l-lp[lb]+1;i<=size[lb];i++) H[lb][i]^=t; for (int i=1;i<=size[lb];i++) Map[lb][H[lb][i]^=tag[lb]]++; tag[lb]=0; Map[rb]._new(); for (int i=1;i<=r-lp[rb]+1;i++) H[rb][i]^=t; for (int i=1;i<=size[rb];i++) Map[rb][H[rb][i]^=tag[rb]]++; tag[rb]=0; } inline int Query(int r,ull t){ int rb=pos[r],ret=0; for (int i=1;i<rb;i++) ret+=Map[i].find(t^tag[i]); for (int i=1;i<=r-lp[rb]+1;i++) ret+=((H[rb][i]^tag[rb])==t); return ret; } int icnt,sx ; inline int Bin(int x){ return lower_bound(sx+1,sx+icnt+1,x)-sx; } int main(){ freopen("gf.in","r",stdin); freopen("gf.out","w",stdout); read(n); for (int i=1;i<=n;i++) read(a[i]),sx[++icnt]=a[i]; sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1; for (int i=1;i<=n;i++){ a[i]=Bin(a[i]); pre[i]=last[a[i]],last[a[i]]=i; } for (int i=1;i<=icnt;i++) S[i]=((ull)rand()<<48)|((ull)rand()<<32)|((ull)rand()<<16)|((ull)rand()); ll ans=0; ull sum=0; Build(n); for (int i=1;i<=n;i++){ Add(pre[i]+1,i,S[a[i]]); sum^=S[a[i]]; ans+=Query(i,sum); } printf("%lld\n",ans); return 0; }
相关文章推荐
- [分块][哈希] [Romanian IOI 2017 Selection #6] Jolteon && [LOJ #6187] Odd
- [JSOI2017]原力(分块+map(hash))
- [分块 莫比乌斯反演] BZOJ 4815 [Cqoi2017]小Q的表格
- SGU 4554 Boring Game 来自队友的神奇随机Hash
- Russian Code Cup 2017 - Finals B. Similar Words(hash+树形dp)
- [分块 回文自动机] LOJ#6070. 「2017 山东一轮集训 Day4」基因
- CF799F,随机+hash
- bzoj 4815: [Cqoi2017]小Q的表格【欧拉函数+分块】
- 一次内存访问、SSD 硬盘访问和SATA 硬盘随机访问的时间(腾讯2017实习生题目)
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor [LCA+分块]
- [P3759][TJOI2017]不勤劳的图书管理员(分块+树状数组)
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 Barty's Computer(暴力+hash)
- HDU 6053 TrickGCD(分块+容斥)——2017 Multi-University Training Contest - Team 2
- HDU 6046 hash (HASH, 2017 Multi-Univ Training Contest 2)
- 2017百度之星资格赛:1005. 寻找母串(卡特兰数+分块打表)
- IOI 2017 Practice Contest mountains
- 【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor
- HDU 3065 2017 Multi-University Training Contest - Team 1 1003 Corlorful Tree:计数+树上分块
- HDU6046 hash 【2017多校联训第二场B】
- HDU3868 HASH+随机增量