hdu5081

题意有点绕,不过读懂了之后并不难

以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 }

时间: 2024-10-21 20:12:04

hdu5081的相关文章