Codeforces Round #629 (Div. 3) E

E - Tree Queries

题意:

给一个n个点的树(以1为树根,每个点的距离是1),然后询问m次,t个点是否在树中的某条链上,如果没在链上,但离链距离是1的也是允许的

思路:

找到 t 个点最深的一个点,以这个点去查找其他点v的最近公共祖先d,最近公共祖先d的深度与v的深度大于1的就直接输出NO,如果全部符合就是YES

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define il inline
 6 #define it register int
 7 #define inf 0x3f3f3f3f
 8 #define lowbit(x) (x)&(-x)
 9 #define pii pair<int,int>
10 #define mak(n,m) make_pair(n,m)
11 #define mem(a,b) memset(a,b,sizeof(a))
12 #define mod 998244353
13 #define fi first
14 #define se second
15 #define sz(x) (int)(x).size()
16 #define all(x) (x).begin(), (x).end()
17 const int maxn=2e5+10;
18 ll ksm(ll a,ll b){if(b<0)return 0;ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;}
19 int n,t,m,tot,d[maxn];
20 struct node{
21     int next,dist,v;
22 }a[maxn<<1];
23 int fath[maxn][20], depth[maxn];
24 int dist[maxn],head[maxn];
25 void add(int u,int v,int dist0){
26     a[tot].next=head[u];
27     a[tot].dist=dist0;
28     a[tot].v=v;
29     head[u]=tot++;
30 }
31 void dfs(int u,int fa,int d) {
32     fath[u][0]=fa; depth[u]=d;
33     for(int i=1;i<20;i++) fath[u][i]=fath[fath[u][i-1]][i-1];
34     for (int i=head[u];~i;i=a[i].next){
35         int v=a[i].v;if(v==fa)continue;
36         dist[v]=dist[u]+a[i].dist;
37         dfs(v,u,d+1);
38     }
39 }
40 void init(int n){
41     for(int i=0;i<=n;i++)fath[i][0]=0,dist[i]=0,head[i]=-1,depth[i]=0;
42     tot=0;
43 }
44 il int lca(int x,int y){
45     if(depth[x]<depth[y])swap(x,y);
46     int h=depth[x]-depth[y];
47     for(it i=0;h>0;i++){
48         if(h&1){
49             x=fath[x][i];
50         }
51         h>>=1;
52     }
53     if(x==y)return x;
54     for(it i=19;i>=0;i--){
55         if(fath[x][i]!=fath[y][i]){
56             x=fath[x][i];
57             y=fath[y][i];
58         }
59     }
60     return fath[x][0];
61 }
62 il int dis(int u,int v){
63     int d=lca(u,v);//cout<<d<<" "<<depth[v]-depth[d]<<endl;
64     if(depth[v]-depth[d]>1){return 1;}
65     return 0;
66 }
67 int main(){
68     scanf("%d%d",&n,&m);
69     init(n);
70     for(it i=1;i<n;i++){int w,v;scanf("%d%d",&w,&v);add(w,v,1);add(v,w,1);}
71     dfs(1,0,1);
72     while(m--){
73         scanf("%d",&t);
74         for(it i=0;i<t;i++){
75             scanf("%d",&d[i]);
76         }
77         int shen=1,pos=1;
78         for(it i=0;i<t;i++){
79             if(depth[d[i]]>shen){
80                 shen=depth[d[i]];pos=d[i];
81             }
82         }
83         int f=1;
84         for(it i=0;i<t;i++){
85             if(dis(pos,d[i])){f=0;break;}
86         }
87         if(f){printf("YES\n");}
88         else{printf("NO\n");}
89     }
90     return 0;
91 }

 

 

顺便说一下比赛过的A~D

A题b-a%b,a%b==0

B题找i*(i+1)/2最接近m的数字,然后m-i*(i+1)/2和i是b的位置(口胡,但当时思路是这样,我为了找i,用o(1)的方法写了50min+,我心态差点裂开了,最后还是用o(sqrtm)找了)

C题第一个1出现之前,0分配0,0;2分配1,1。当1出现了分配1,0。第一个1出现之后0分配0,0;1分配0,1;2分配0,2 。

D题只会出现1,2,3,只出现一个数是1,偶数就是2,以12循环n/2次,如果是奇数,如果有两个相同数连一块的,首位也要算进去,就是2,以1,2循环,直到出现相同数连一块,他们的颜色相同然后1,2的隔开,其余的就是3种颜色,以12循环n/2次,最后一位是3

posted @ 2020-03-27 21:10  ouluy  阅读(197)  评论(0编辑  收藏  举报