标签:clr cte clu bfs 区间 add long back span
题意有点绕,不过读懂了之后并不难
以Si结尾容易想到ac自动机,建好ac自动机并将fail指针反向即可得到一棵树
那么操作1就是将若干个子树的并中的节点全部权值+1
操作2就是将求若干个节点到根的路径的并中的节点的权值和
操作1不难用dfs序将子树并转化为区间并然后线段树区间加
操作2呢,我们进行树链剖分,对于每条重链,在重链头记录一下这条重链之前询问到哪个位置了
因为每个点到根的路径都是若干重链的若干前缀,这样问题就解决了
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 int go[100010][27],a[500010],fa[100010],laz[400010],l[100010],r[100010],c[100010],q[100010],s[100010],nex[100010],top[100010],f[100010],d[100010]; 6 int n,m,k,t,ch; 7 vector<int> g[100010]; 8 bool v[100010]; 9 ll tr[400010]; 10 char ss[2]; 11 12 bool cmp(int a,int b) 13 { 14 if (l[a]==l[b]) return r[a]<r[b]; 15 return l[a]<l[b]; 16 } 17 18 void bfs() 19 { 20 int h=1,r=0; 21 for (int i=0; i<26; i++) 22 if (go[0][i]) 23 { 24 g[1].push_back(go[0][i]+1); 25 q[++r]=go[0][i]; 26 } 27 while (h<=r) 28 { 29 int x=q[h++]; 30 for (int i=0; i<26; i++) 31 if (go[x][i]) 32 { 33 int y=go[x][i]; 34 q[++r]=y; 35 int j=f[x]; 36 while (j>0&&!go[j][i]) j=f[j]; 37 f[y]=go[j][i]; 38 g[go[j][i]+1].push_back(y+1); 39 } 40 } 41 } 42 43 void dfs(int x) 44 { 45 s[x]=1; 46 for (int i=0; i<g[x].size(); i++) 47 { 48 int y=g[x][i]; 49 // cout <<x<<" "<<y<<endl; 50 d[y]=d[x]+1; 51 fa[y]=x; 52 dfs(y); 53 s[x]+=s[x]; 54 } 55 } 56 57 void get(int x) 58 { 59 l[x]=++t; 60 int q=0; 61 for (int i=0; i<g[x].size(); i++) 62 { 63 int y=g[x][i]; 64 if (s[y]>s[q]) q=y; 65 } 66 if (q) 67 { 68 top[q]=top[x]; 69 get(q); 70 } 71 nex[x]=q; 72 for (int i=0; i<g[x].size(); i++) 73 { 74 int y=g[x][i]; 75 if (y!=q) 76 { 77 top[y]=y; 78 get(y); 79 } 80 } 81 r[x]=t; 82 } 83 84 void push(int i,int l,int r) 85 { 86 int m=(l+r)>>1; 87 tr[i*2]+=1ll*laz[i]*(m+1-l); 88 tr[i*2+1]+=1ll*laz[i]*(r-m); 89 laz[i*2]+=laz[i]; 90 laz[i*2+1]+=laz[i]; 91 laz[i]=0; 92 } 93 94 void add(int i,int l,int r,int x,int y) 95 { 96 if (x<=l&&y>=r) 97 { 98 tr[i]+=(r-l+1); 99 laz[i]++; 100 } 101 else { 102 int m=(l+r)>>1; 103 if (laz[i]) push(i,l,r); 104 if (x<=m) add(i*2,l,m,x,y); 105 if (y>m) add(i*2+1,m+1,r,x,y); 106 tr[i]=tr[i*2]+tr[i*2+1]; 107 } 108 } 109 110 ll ask(int i,int l,int r,int x,int y) 111 { 112 if (x<=l&&y>=r) return tr[i]; 113 else { 114 int m=(l+r)>>1; ll s=0; 115 if (laz[i]) push(i,l,r); 116 if (x<=m) s+=ask(i*2,l,m,x,y); 117 if (y>m) s+=ask(i*2+1,m+1,r,x,y); 118 return s; 119 } 120 } 121 122 ll getans(int x) 123 { 124 ll s=0; 125 while (x) 126 { 127 int y=top[x]; 128 if (!c[y]||d[c[y]]>d[x]) return s; 129 s+=ask(1,1,n,l[c[y]],l[x]); 130 if (c[y]!=y) {c[y]=nex[x]; return s;} 131 c[y]=nex[x]; x=fa[y]; 132 if (!v[y]) 133 { 134 q[++t]=y; 135 v[y]=1; 136 } 137 } 138 return s; 139 } 140 141 void clr() 142 { 143 for (int i=1; i<=t; i++) 144 { 145 int x=q[i]; 146 v[x]=0; c[x]=x; 147 } 148 t=0; 149 } 150 151 int main() 152 { 153 int cas; 154 scanf("%d",&cas); 155 while (cas--) 156 { 157 scanf("%d",&n); 158 memset(go,0,sizeof(go)); 159 memset(f,0,sizeof(f)); 160 for (int i=2; i<=n; i++) 161 { 162 int x; 163 scanf("%d%s",&x,&ss); 164 go[x-1][ss[0]-‘a‘]=i-1; 165 } 166 for (int i=1; i<=n; i++) g[i].clear(); 167 bfs(); t=0; 168 dfs(1); top[1]=1; get(1); 169 for (int i=1; i<=n; i++) c[i]=i; 170 memset(tr,0,sizeof(tr)); 171 memset(laz,0,sizeof(laz)); 172 scanf("%d",&m); t=0; 173 for (int i=1; i<=m; i++) 174 { 175 scanf("%d",&ch); 176 scanf("%d",&k); 177 for (int j=1; j<=k; j++) scanf("%d",&a[j]); 178 if (ch==1) 179 { 180 sort(a+1,a+1+k,cmp); 181 int b=l[a[1]],e=r[a[1]]; 182 for (int j=2; j<=k; j++) 183 { 184 if (e<l[a[j]]) 185 { 186 add(1,1,n,b,e); 187 b=l[a[j]]; 188 e=r[a[j]]; 189 } 190 else e=max(e,r[a[j]]); 191 } 192 add(1,1,n,b,e); 193 } 194 else { 195 ll ans=0; 196 for (int j=1; j<=k; j++) ans+=getans(a[j]); 197 clr(); 198 printf("%lld\n",ans); 199 } 200 } 201 } 202 }
标签:clr cte clu bfs 区间 add long back span
原文地址:http://www.cnblogs.com/phile/p/6378531.html