题意:
给一个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 ");} 88 else{printf("NO ");} 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