NC212177. brz的扑克
描述
输入描述
第一行一个整数 n,表示树的大小。
下面 n 行每行两个整数,第 i 行的两个数分别表示第 i 个节点上的扑克的正反两面上的数字。
下面 n-1 行每行两个整数 x,y,表示节点 x 与节点 y 之间有一条边。
下面一行一个整数 m 表示询问数量。下面 m 行每行两个整数 x,y,表示一次询问,注意,询问之间相互独立,即每次询问完后会把扑克放回树上的原位置。
扑克上的数字 。
输出描述
输出 m 行每行一个数,第 i 行的数表示第 i 组询问能找到的最长顺子的长度。
示例1
输入:
6 2 4 1 3 1 2 3 4 5 6 7 8 1 2 2 3 2 4 1 5 5 6 2 3 4 2 6
输出:
3 3
说明:
样例的树长这样:C++(clang++11) 解法, 执行用时: 375ms, 内存消耗: 17784K, 提交时间: 2020-11-10 21:14:43
#include<bits/stdc++.h> using namespace std; const int M=1e5+9; int n,m,num=0,root; int head[M],ma[M],siz[M],va[M][2]; struct P{int to,ne;}e[M<<1]; struct Q{int y,id,o;}; vector<Q>g[M]; int in[M],kind[M],val[M][2],ans[M],up[M][2][2],dw[M][2][2]; int li[M][2],ri[M][2]; bool vis[M]; int read(){ int rex=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){rex=rex*10+ch-'0';ch=getchar();} return rex*f; } void findroot(int u,int fa,int sum){ ma[u]=0,siz[u]=1; for(int i=head[u];i;i=e[i].ne){ int v=e[i].to; if(v!=fa&&!vis[v]){ findroot(v,u,sum); siz[u]+=siz[v]; ma[u]=max(ma[u],siz[v]); } } ma[u]=max(ma[u],sum-siz[u]); if(ma[u]<ma[root])root=u; } void solve(int u,int fa,int o,int deep){ int mi[2];kind[u]=o;in[u]=root; mi[0]=mi[1]=0; for(int i=0;i<=1;++i){ for(int j=0;j<=1;++j) up[u][i][j]=up[fa][i][j], dw[u][i][j]=dw[fa][i][j]; if(fa!=root) for(int j=0;j<=1;++j) for(int k=0;k<=1;++k){ if(up[fa][j][k]==deep&&va[u][i]==va[fa][j]+1)up[u][i][k]=deep+1; if(dw[fa][j][k]==deep&&va[u][i]==va[fa][j]-1)dw[u][i][k]=deep+1; } else { for(int j=0;j<=1;++j){ if(va[u][i]==va[fa][j]+1)up[u][i][j]=2; if(va[u][i]==va[fa][j]-1)dw[u][i][j]=2; } } } for(int i=0;i<=1;++i){ li[u][i]=ri[u][i]=1; for(int j=0;j<=1;++j){ if(va[u][i]==va[fa][j]+1)li[u][i]=max(li[u][i],li[fa][j]+1); if(va[u][i]==va[fa][j]-1)ri[u][i]=max(ri[u][i],ri[fa][j]+1); } mi[0]=max(mi[0],li[u][i]); mi[1]=max(mi[1],ri[u][i]); } mi[0]=max(mi[0],val[fa][0]); mi[1]=max(mi[1],val[fa][1]); val[u][0]=mi[0]; val[u][1]=mi[1]; for(int i=0,s=g[u].size();i<s;++i){ int v=g[u][i].y,id=g[u][i].id,x=g[u][i].o; if(kind[v]!=kind[u]&&in[v]==root){ if(x==1)ans[id]=max(val[u][1],val[v][0]); else ans[id]=max(val[u][0],val[v][1]); for(int j=0;j<=1;++j) for(int k=0;k<=1;++k) for(int l=0;l<=1;++l){ if(x==-1)ans[id]=max(ans[id],up[u][j][l]+dw[v][k][l]-1); else ans[id]=max(ans[id],dw[u][j][l]+up[v][k][l]-1); } } } for(int i=head[u];i;i=e[i].ne){ int v=e[i].to; if(v!=fa&&!vis[v])solve(v,u,o,deep+1); } } void dfs(int u,int sum){ root=0; findroot(u,0,sum); u=root; val[u][0]=val[u][1]=vis[u]=1; in[u]=u; kind[u]=0; for(int i=0;i<=1;++i)li[u][i]=ri[u][i]=1; for(int i=0;i<=1;++i) for(int j=0;j<=1;++j) up[u][i][j]=dw[u][i][j]=1; for(int i=head[u];i;i=e[i].ne){ int v=e[i].to; if(!vis[v])solve(v,u,v,1); } for(int i=head[u];i;i=e[i].ne){ int v=e[i].to; if(!vis[v])dfs(v,siz[v]); } } int main(){ //freopen("1.in","r",stdin); //freopen("m.txt","w",stdout); n=read(); for(int i=1;i<=n;++i)va[i][0]=read(),va[i][1]=read(); for(int i=1,x,y;i<n;++i){ x=read(),y=read(); e[++num]=P{y,head[x]};head[x]=num; e[++num]=P{x,head[y]};head[y]=num; } m=read(); for(int i=1,x,y;i<=m;++i){ x=read(),y=read(); g[x].push_back(Q{y,i,1}); g[y].push_back(Q{x,i,-1}); if(x==y)ans[i]=1; } ma[0]=1e9; dfs(1,n); for(int i=1;i<=m;++i)printf("%d\n",ans[i]); return 0; }