题意:T组数据,每次给你1e5个点的树(1为根),每个点有一权值,询问1-n每个节点的子树中,
至少修改几个点的权值(每次都可以任意修改),才能让子树中任意2点的距离==他们权值差的绝对值
无解输出-1
题解:画图不难发现,如果这个节点有3个儿子,也就是不包含它连向它父亲的边,它还有多于2条边的话,一定不行
因为子节点权值只能是这个节点+1或者-1,所以只能存在最多2个
那我们就又发现了,只有这个子树,可以拉成一个链的时候,才有答案,
考虑在链中的情况,如何判断修改最少的个数,使得这是个差为1的等差数列
一个显然的做法,每个数减去i,比如1 4 3 5 6 3 7,每个数减去位置0 2 0 1 2 -3 0
众数是0,有3个,所以答案就是7-3==4,至少修改4个数
我们再考虑合并的情况,可以使用启发式合并,每次让儿子数少的并向多的
可是我们又发现,这个节点一旦是2棵子树合并过了,他这颗子树就废掉了,以后就不会再用了
因为这个链已经使用了,而继续传回去的点是这个父节点,它又不在链的两端,所以总的复杂度O(n)
多组数据的清空怕T,所以在使用后,马上进行了清空,代码有点冗余
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100007 4 int n,v[N],siz[N],de[N],vis[N],T,u,w; 5 vector<int> g[N]; 6 int now,cnt1[2][N*3],mx1[2],cnt2[2][N*3],mx2[2]; 7 int nod[2][N],tot[2],ad[N*3],mxx,ans[N]; 8 bool dfs(int x,int dep) 9 { 10 vis[x]=1; 11 siz[x]=1; 12 de[x]=dep; 13 bool re=1; 14 int cnt=0; 15 for(int i=0;i<g[x].size();i++) 16 if(!vis[g[x][i]]) 17 { 18 if(cnt != 0) 19 { 20 now^=1; 21 mx1[now]=mx2[now]=0; 22 for(int j=1;j<=tot[now];j++) 23 { 24 int xx=nod[now][j]; 25 cnt1[now][v[xx]-de[xx]]=0; 26 cnt2[now][v[xx]+de[xx]]=0; 27 } 28 tot[now]=0; 29 } 30 re&=dfs(g[x][i],dep+1),siz[x]+=siz[g[x][i]]; 31 cnt++; 32 } 33 if(!re || g[x].size()>3 || (x==1 && g[x].size()==3)) 34 { 35 ans[x]=-1; 36 return 0; 37 } 38 if(g[x].size()==3 || (x==1 && g[x].size()==2)) 39 { 40 int tmp = 1; 41 mxx = 0; 42 for(int i = 1; i <= tot[now]; i++) 43 { 44 int xx = nod[now][i]; 45 ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++; 46 } 47 ad[v[x] - tmp]++; mxx = max(mxx, ad[v[x] - tmp]); tmp++; 48 for(int i = tot[now ^ 1]; i >= 1; i--) 49 { 50 int xx = nod[now ^ 1][i]; 51 ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++; 52 } 53 ans[x] = siz[x] - mxx; 54 55 tmp = 1; 56 for(int i = 1; i <= tot[now]; i++) 57 { 58 int xx = nod[now][i]; 59 ad[v[xx] - tmp]--; tmp++; 60 } 61 ad[v[x] - tmp]--; tmp++; 62 for(int i = tot[now ^ 1]; i >= 1; i--) 63 { 64 int xx = nod[now ^ 1][i]; 65 ad[v[xx] - tmp]--; tmp++; 66 } 67 68 tmp = 1; 69 mxx = 0; 70 for(int i = 1; i <= tot[now]; i++) 71 { 72 int xx = nod[now][i]; 73 ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++; 74 } 75 ad[v[x] + tmp]++; mxx = max(mxx, ad[v[x] + tmp]); tmp++; 76 for(int i = tot[now ^ 1]; i >= 1; i--) 77 { 78 int xx = nod[now ^ 1][i]; 79 ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++; 80 } 81 ans[x] = min(ans[x], siz[x] - mxx); 82 tmp = 1; 83 for(int i = 1; i <= tot[now]; i++) 84 { 85 int xx = nod[now][i]; 86 ad[v[xx] + tmp]--; tmp++; 87 } 88 ad[v[x] + tmp]--; tmp++; 89 for(int i = tot[now ^ 1]; i >= 1; i--) 90 { 91 int xx=nod[now^1][i]; 92 ad[v[xx]+tmp]--;tmp++; 93 } 94 return 0; 95 } 96 nod[now][++tot[now]]=x; 97 cnt1[now][v[x]-dep]++; 98 if(cnt1[now][v[x]-dep]>mx1[now]) mx1[now]=cnt1[now][v[x]-dep]; 99 cnt2[now][v[x]+dep]++; 100 if(cnt2[now][v[x]+dep]>mx2[now]) mx2[now]=cnt2[now][v[x]+dep]; 101 ans[x]=siz[x]-max(mx1[now], mx2[now]); 102 return 1; 103 } 104 int main() 105 { 106 scanf("%d",&T); 107 while(T--) 108 { 109 scanf("%d",&n); 110 now=0; 111 mx1[now]=mx2[now]=0; 112 for(int j=1;j<=tot[now];j++) 113 { 114 int xx=nod[now][j]; 115 cnt1[now][v[xx]-de[xx]]=0; 116 cnt2[now][v[xx]+de[xx]]=0; 117 } 118 tot[now]=0; 119 now=1; 120 mx1[now]=mx2[now]=0; 121 for(int j=1;j<=tot[now];j++) 122 { 123 int xx=nod[now][j]; 124 cnt1[now][v[xx]-de[xx]]=0; 125 cnt2[now][v[xx]+de[xx]]=0; 126 } 127 tot[now] = 0; 128 now = 0; 129 for(int i=1;i<=n;i++) vis[i]=0,ans[i]=0; 130 for(int i=1;i<=n;i++) g[i].clear(); 131 for(int i=1;i<=n;i++) scanf("%d",&v[i]),v[i]+=100000; 132 for(int i=1;i<n;i++) 133 { 134 scanf("%d%d",&u,&w); 135 g[u].push_back(w); 136 g[w].push_back(u); 137 } 138 dfs(1,1); 139 for(int i = 1; i <= n; i++) printf("%d ", ans[i]); 140 puts(""); 141 } 142 }
不挤在一次dfs里好像就短多了
1 #include<bits/stdc++.h> 2 #define lld long long 3 #define N 300007 4 using namespace std; 5 int T,n,nn,pn,u,w; 6 int v[N],dep[N],fa[N],dp[N],dq[N]; 7 int ch[N],ok[N],p[N],ans[N],sz[N]; 8 vector<int> g[N]; 9 void DFS(int x) 10 { 11 for (auto e: g[x]) if (e!=fa[x]) DFS(e); 12 p[pn++]=x; 13 } 14 void work(int id) 15 { 16 int t; 17 for (int i=0;i<pn;i++) 18 { 19 if (id==-1) t=p[i];else t=id; 20 ans[t]=max(ans[t],++dq[v[p[i]]+i]); 21 ans[t]=max(ans[t],++dp[v[p[i]]-i]); 22 if (i && id==-1) ans[p[i]]=max(ans[p[i]],ans[p[i-1]]); 23 } 24 for (int i=0;i<pn;i++) 25 { 26 dp[v[p[i]]-i]--; 27 dq[v[p[i]]+i]--; 28 } 29 } 30 void solve(int x) 31 { 32 pn=0; 33 DFS(x); 34 work(-1); 35 } 36 void solve2(int x) 37 { 38 pn=0; 39 int tn=-1; 40 for (auto e: g[x]) if (e!=fa[x]) 41 { 42 DFS(e); 43 if (tn==-1) 44 { 45 p[pn++]=x; 46 tn=pn; 47 } 48 } 49 reverse(p+tn,p+pn); 50 work(x); 51 } 52 void dfs(int x) 53 { 54 ok[x]=sz[x]=1; 55 ch[x]=0; 56 for (auto e:g[x]) if (e!=fa[x]) 57 { 58 ch[x]++; 59 fa[e]=x; 60 dfs(e); 61 sz[x]+=sz[e]; 62 ok[x]&=ok[e]; 63 } 64 ok[x]&=ch[x]<=1; 65 if (!ok[x]) 66 { 67 for (auto e:g[x]) if (e!=fa[x] && ok[e]) solve(e); 68 if (ch[x]==2) 69 { 70 int c=0; 71 for (auto e:g[x]) if (e!=fa[x] && ok[e]) c++; 72 if (c==2) solve2(x); 73 } 74 } 75 } 76 int main() 77 { 78 scanf("%d",&T); 79 while (T--) 80 { 81 scanf("%d",&n); 82 for (int i=0;i<n;i++) 83 { 84 g[i].clear(); 85 scanf("%d",&v[i]); 86 v[i]+=n; 87 ans[i]=-1; 88 } 89 for (int i=1;i<n;i++) 90 { 91 scanf("%d%d",&u,&w); 92 u--;w--; 93 g[u].emplace_back(w); 94 g[w].emplace_back(u); 95 } 96 fa[0]=-1; 97 dfs(0); 98 if (ok[0]) solve(0); 99 for (int i=0;i<n;i++) printf("%d ",ans[i]==-1?-1:sz[i]-ans[i]); 100 puts(""); 101 } 102 }