先思考一下序列上应该怎么做。
如果某段和为x,并且x为偶数,那么比x小的偶数,一定是这段的子段。
如果某段和为x,并且x为奇数,那么比x小的奇数,一定是这段的子段。
因此....只要寻找最大的连续的和为奇数的是多少,偶数的是多少。然后对询问就可以o(1)输出了。
推广到树上,就是只要计算路径上最大的奇数和最大的偶数。 树dp即可解决。 树dp写搓了。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> #include<ctime> using namespace std; typedef long long LL; const double pi=acos(-1.0); void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } int n,q; bool f[200010],L[200010]; struct Edge { int u,v,w,nx; }e[200010]; int sz,h[100010]; int mx[100010][2]; int max0,max1; int a[100]; struct X { int from, num; X() { num = 0; from = 0; } X(int From,int Num) { from=From; num=Num; } bool operator < (const X &a) const { return num<a.num; } }; void add(int a,int b,int c) { e[sz].u=a; e[sz].v=b; e[sz].w=c; e[sz].nx=h[a]; h[a]=sz++; } struct cmp{ bool operator ()(int &a,int &b) { return a<b; } }; void dfs(int x) { f[x]=1; priority_queue<X>Q[3]; for(int i=h[x];i!=-1;i=e[i].nx) { if(f[e[i].v]==1) continue; mx[x][e[i].w%2]=e[i].w; dfs(e[i].v); if(mx[e[i].v][0]!=-1) Q[(e[i].w+mx[e[i].v][0])%2].push(X(e[i].v,e[i].w+mx[e[i].v][0])); if(mx[e[i].v][1]!=-1) Q[(e[i].w+mx[e[i].v][1])%2].push(X(e[i].v,e[i].w+mx[e[i].v][1])); if(mx[e[i].v][0]==-1||mx[e[i].v][1]==-1) { if(Q[(e[i].w)%2].empty()) Q[(e[i].w)%2].push(X(e[i].v,e[i].w)); } } if(!Q[0].empty()) mx[x][0]=Q[0].top().num; if(!Q[1].empty()) mx[x][1]=Q[1].top().num; int p=0; X f1,f2,g1,g2; if(!Q[0].empty()) { f1=Q[0].top(); Q[0].pop(); } if(!Q[0].empty()) { f2=Q[0].top(); Q[0].pop(); } if(!Q[1].empty()) { g1=Q[1].top(); Q[1].pop(); } if(!Q[1].empty()) { g2=Q[1].top(); Q[1].pop(); } if(f1.num+f2.num!=0) a[p++]=f1.num+f2.num; if(g1.num+g2.num!=0) a[p++]=g1.num+g2.num; if(f1.from!=g1.from) { if(f1.num+g1.num!=0) a[p++]=f1.num+g1.num; } else { if(f1.num+g2.num!=0) a[p++]=f1.num+g2.num; if(f2.num+g1.num!=0) a[p++]=f2.num+g1.num; } for(int i=0;i<p;i++) { if(a[i]%2==0) max0=max(max0,a[i]); if(a[i]%2==1) max1=max(max1,a[i]); } } int main() { while(~scanf("%d%d",&n,&q)) { memset(f,sz=0,sizeof f); memset(h,-1,sizeof h); memset(L,0,sizeof L); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } memset(mx,-1,sizeof mx); max0=max1=-1; dfs(1); for(int i=1;i<=q;i++) { int x; scanf("%d",&x); if(x<0) printf("No\n"); else { if(x%2==0) { if(max0>=x) printf("Yes\n"); else printf("No\n"); } if(x%2==1) { if(max1>=x) printf("Yes\n"); else printf("No\n"); } } } } return 0; }
时间: 2024-10-07 05:30:43