[51nod Round15 E ]Danganronpa
AC自动机,树上莫队,树状数组。。
比赛的时候完全看不出来...赛后去膜了一波网上题解才明白= =
离线,先把AC自动机建出来,把fail边反向建出fail树。
发射言弹,就是将言弹结束节点的fail子树内点权+1;
查询证言受的伤害,就是查询证言的每个前缀的结束节点的点权和。
前缀的结束节点的点权和,也就是AC自动机上,根到证言结束位置路径上的点权和。
每一个查询,就是查询在一段时间内,根到证言结束位置路径上的点权和。。。
所以就树上莫队一波了。。前两维时间,第三维是AC自动机上的位置。。再来个树状数组维护一波...
时间复杂度O(n^(3/5)logn)。。。。卡时过的。。。还要注意一下块的大小。。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define ll long long 7 using namespace std; 8 const int maxn=100233<<1; 9 struct zs{int too,pre;}e[maxn];int tt,last[maxn]; 10 struct ask{int x,tim,timl,id;}b[maxn]; 11 int B[maxn]; 12 int ch[maxn][26],fail[maxn],dl[maxn],cnt; 13 int dfn[maxn],mp[maxn],TIME,L[maxn],R[maxn],TIM; 14 int pos[maxn],pos1[maxn],tim1[maxn],a[maxn]; 15 int i,j,k,n,m; 16 ll sum,an[maxn]; 17 bool u[maxn]; 18 19 int ra;char rx; 20 inline int read(){ 21 rx=getchar(),ra=0; 22 while(rx<'0'||rx>'9')rx=getchar(); 23 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 24 } 25 26 void dfs(int x){ 27 L[x]=++TIM; 28 for(int i=last[x];i;i=e[i].pre) 29 dfs(e[i].too); 30 R[x]=TIM;//printf(" x:%d l--r:%d %d\n",x,L[x],R[x]); 31 } 32 void dfs2(int x){ 33 dfn[x]=++TIME,mp[TIME]=x;//printf("x:%d dfn:%d\n",x,dfn[x]); 34 for(int i=0;i<26;i++)if(ch[x][i]) 35 dfs2(ch[x][i]); 36 mp[++TIME]=x; 37 } 38 inline void insert(int a,int b){e[++tt].too=b,e[tt].pre=last[a],last[a]=tt;/*printf("%d-->%d\n",a,b);*/} 39 40 int t[maxn],t1[maxn]; 41 inline void add1(int x){/*printf(" add1:%d\n",x);*/while(x<=cnt)t1[x]++,x+=x&-x;} 42 inline void del1(int x){/*printf(" del1:%d\n",x);*/while(x<=cnt)t1[x]--,x+=x&-x;} 43 inline int get1(int l,int r){ 44 int sm=0;//printf(" get1:%d--%d",l,r); 45 l--;while(l)sm-=t1[l],l-=l&-l; 46 while(r)sm+=t1[r],r-=r&-r;/*printf(": %d\n",sm);*/return sm; 47 } 48 49 inline int get(int x){ 50 // printf("get:%d",x); 51 int sm=0;while(x)sm+=t[x],x-=x&-x;//printf(" %d\n",sm); 52 return sm; 53 } 54 inline void add(int l,int r){ 55 if(!l)return;//printf("add: %d--%d\n",l,r); 56 sum+=get1(l,r); 57 while(l<=cnt)t[l]++,l+=l&-l; 58 r++;while(r<=cnt)t[r]--,r+=r&-r; 59 } 60 inline void del(int l,int r){ 61 if(!l)return;//printf("del: %d--%d\n",l,r); 62 sum-=get1(l,r); 63 while(l<=cnt)t[l]--,l+=l&-l; 64 r++;while(r<=cnt)t[r]++,r+=r&-r; 65 } 66 67 68 void getfail(){ 69 int l=0,r=1,i,p,now,j;dl[1]=0; 70 while(l<r){ 71 now=dl[++l]; 72 for(i=0;i<26;i++)if(ch[now][i]){ 73 dl[++r]=j=ch[now][i]; 74 for(p=fail[now];p&&!ch[p][i];p=fail[p]); 75 fail[j]=!now?0:ch[p][i],insert(fail[j],j); 76 } 77 } 78 } 79 80 bool cmp(ask a,ask b){ 81 return B[a.timl]==B[b.timl]?(B[a.tim]==B[b.tim]?a.x<b.x:B[a.tim]<B[b.tim]):B[a.timl]<B[b.timl]; 82 } 83 int main(){ 84 m=read();char id[13],c[2];int x,tm=0,numb=0,n=0,n1=0; 85 for(i=1;i<=m;i++){ 86 scanf("%s",id); 87 if(id[0]=='I'){ 88 n++,scanf("%s",c),c[0]-='a',x=read(); 89 if(!ch[pos[x]][c[0]])ch[pos[x]][c[0]]=++cnt;//printf(" .. %d %d\n",pos[x],c[0]); 90 pos[n]=ch[pos[x]][c[0]];//,tim[n]=tm; 91 } 92 if(id[0]=='A'){ 93 n1++,scanf("%s",c),c[0]-='a',x=read(); 94 if(!ch[pos1[x]][c[0]])ch[pos1[x]][c[0]]=++cnt;//,printf(" %d %d\n",pos1[x],c[0]); 95 pos1[n1]=ch[pos1[x]][c[0]],tim1[n1]=tm; 96 } 97 if(id[0]=='S') 98 tm++,a[tm]=pos[read()]; 99 if(id[0]=='Q') 100 b[++numb].x=read(),b[numb].tim=tm,b[numb].timl=tim1[b[numb].x]+1,b[numb].id=numb; 101 } 102 cnt++; 103 getfail(); 104 dfs(0),dfs2(0);int kuai=(int)pow(tm,1.8/3)+3; 105 for(i=0;i<=tm+1;i++)B[i]=(i+kuai-1)/kuai; 106 for(i=1;i<=numb;i++)b[i].x=dfn[pos1[b[i].x]]; 107 sort(b+1,b+1+numb,cmp); 108 109 int l=1,r=0,pos=1;L[0]=R[0]=0,u[mp[1]]=1; 110 for(i=1;i<=numb;i++){ 111 // printf("ask: %d--%d %d--%d x:%d sum:%lld\n",b[i].timl,b[i].tim,B[b[i].timl],B[b[i].tim],b[i].x,sum); 112 while(l>b[i].timl)l--,add(L[a[l]],R[a[l]]); 113 while(r<b[i].tim)r++,add(L[a[r]],R[a[r]]); 114 while(l<b[i].timl)del(L[a[l]],R[a[l]]),l++; 115 while(r>b[i].tim)del(L[a[r]],R[a[r]]),r--;//printf("sum: %lld\n",sum); 116 while(pos>b[i].x){ 117 if(u[mp[pos]])sum-=get(L[mp[pos]]),del1(L[mp[pos]]);else sum+=get(L[mp[pos]]),add1(L[mp[pos]]); 118 u[mp[pos]]^=1,pos--; 119 } 120 while(pos<b[i].x){ 121 pos++;//printf("x: %d dfn:%d L:%d\n",mp[pos],pos,L[mp[pos]]); 122 if(u[mp[pos]])sum-=get(L[mp[pos]]),del1(L[mp[pos]]);else sum+=get(L[mp[pos]]),add1(L[mp[pos]]); 123 u[mp[pos]]^=1; 124 } 125 an[b[i].id]=sum; 126 } 127 for(i=1;i<=numb;i++)printf("%lld\n",an[i]); 128 }