解题:CF570D Tree Requests

题面

DSU on tree确实很厉害,然后这变成了一道裸题(逃

还是稍微说一下流程吧,虽然我那个模板汇总里写过

DSU on tree可以以$O(n\log n)$的复杂度解决树上子树统计问题,它这样工作:

前置工作:对树进行轻重链剖分

1.递归求解所有的轻儿子,在回溯时消去影响

2.递归进入重儿子,在回溯时不消去影响

3.暴力统计子树信息

4.回答询问并回溯

根据轻重链剖分的性质,复杂度$O(n\log n)$

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=500005;
 7 vector<pair<int,int> > qry[N];
 8 int siz[N],dep[N],imp[N],sta[N],vis[N],outp[N];
 9 int p[N],noww[2*N],goal[2*N];
10 int n,m,t1,t2,rd,cnt;
11 char str[N];
12 void Link(int f,int t)
13 {
14     noww[++cnt]=p[f];
15     goal[cnt]=t,p[f]=cnt;
16     noww[++cnt]=p[t];
17     goal[cnt]=f,p[t]=cnt;
18 }
19 int Bitcount(int s)
20 {
21     int ret=0;
22     while(s)
23         ret++,s-=s&-s;
24     return ret;
25 }
26 void DFS(int nde,int fth,int dth)
27 {
28     int tmp=0;
29     siz[nde]=1,dep[nde]=dth;
30     for(int i=p[nde];i;i=noww[i])
31         if(goal[i]!=fth)
32         {
33             DFS(goal[i],nde,dth+1);
34             siz[nde]+=siz[goal[i]];
35             if(siz[goal[i]]>tmp)
36                 tmp=siz[goal[i]],imp[nde]=goal[i];
37         }
38 }
39 void Count(int nde,int fth)
40 {
41     sta[dep[nde]]^=1<<(str[nde]-'a');
42     for(int i=p[nde];i;i=noww[i])
43         if(goal[i]!=fth&&!vis[goal[i]])
44             Count(goal[i],nde);
45 }
46 void Getans(int nde,int fth,int hvy)
47 {
48     for(int i=p[nde];i;i=noww[i])
49         if(goal[i]!=fth&&goal[i]!=imp[nde])
50             Getans(goal[i],nde,0);
51     if(imp[nde])
52         Getans(imp[nde],nde,1),vis[imp[nde]]=true;
53     Count(nde,fth);
54     vector<pair<int,int> >::iterator it;
55     for(it=qry[nde].begin();it!=qry[nde].end();it++)
56     {
57         int dth=it->second;
58         outp[it->first]=(Bitcount(sta[dth])<=1);
59     }
60     if(imp[nde]) vis[imp[nde]]=false;
61     if(!hvy) Count(nde,fth);
62 }
63 int main()
64 {
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<n;i++)
67         scanf("%d",&t1),Link(t1,i+1);
68     scanf("%s",str+1);
69     for(int i=1;i<=m;i++)
70     {
71         scanf("%d%d",&t1,&t2);
72         qry[t1].push_back(make_pair(i,t2));
73     }
74     DFS(1,0,1),Getans(1,0,0);
75     for(int i=1;i<=m;i++)
76         outp[i]?puts("Yes"):puts("No");
77     return 0;
78 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10162633.html