Gym

题面

题意: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 } 
原文地址:https://www.cnblogs.com/qywhy/p/10830166.html