您的位置:首页 > 其它

[分块 随机Hash] Romanian IOI 2017 Selection #6 Jolteon

2017-07-01 22:41 260 查看
传送门

问有多少个区间,出现过的数出现次数都是奇数

给每个数随机一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: