题面

题意: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

Gym - 101972B Arabella Collegiate Programming Contest (2018) B. Updating the Tree 树DFS相关推荐

  1. 2015 ACM Arabella Collegiate Programming Contest(F题)

    F. Palindrome [ Color: Pink ] A string is palindrome if it can be read the same way in either direct ...

  2. Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest

    比赛链接: http://codeforces.com/gym/100676 题目链接: http://codeforces.com/gym/100676/attachments/download/3 ...

  3. Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)

    A(By talker): 题意分析:以a(int) op b(int)形式给出两个整数和操作符, 求两个整数是否存在操作符所给定的关系 ,有则输出true,无则输出false:思路:由于无时间复杂度 ...

  4. 2018 ACM ICPC Arabella Collegiate Programming Contest A

    Multiplication operation is not always easy! For example, it is hard to calculate 27 × 20 using your ...

  5. A - Multiplication Dilemma (思维)( 2018 ACM ICPC Arabella Collegiate Programming Contest)

    滴答滴答---题目链接 Multiplication operation is not always easy! For example, it is hard to calculate 27 × 2 ...

  6. 2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解

    F. Monkeying Around   维护点在多少个线段上 http://codeforces.com/gym/101350/problem/F 题意:有m个笑话,每个笑话的区间是[L, R], ...

  7. 2015 ACM Arabella Collegiate Programming Contest

    题目链接:https://vjudge.net/contest/154238#overview. ABCDE都是水题. F题,一开始分类讨论,结果似乎写挫了,WA了一发.果断换并查集上,A了. G题, ...

  8. 2017 ACM Arabella Collegiate Programming Contest(solved 11/13)

    省选考前单挑做点ACM练练细节还是很不错的嘛- 福利:http://codeforces.com/gym/101350 先来放上惨不忍睹的virtual participate成绩(中间跑去食堂吃饭于 ...

  9. gym100676 [小熊骑士限定]2015 ACM Arabella Collegiate Programming Contest

    Kuma Rider久违的第二场训练,这场很水,又在vj的榜单上看到第一场的大哥了,2小时ak,大哥牛啤! A.水 #include<cstdio> #include<iostrea ...

最新文章

  1. TensorFlow指定CPU和GPU方法
  2. python 权限控制 linux_16linux的acl的控制权限的介绍
  3. 神经网络粒子和物理粒子的一个本质差别
  4. dock怎么自定义_如何自定义和调整Mac的Dock
  5. unity获取电磁笔压感_【WPF】获取电磁笔的压感
  6. html5 载入网页 显示,页面加载完之前显示Loading
  7. LinkedList作者说他自己都不用LinkedList?看完给我整不会了。。
  8. 程序员 论坛 linux,用了五年Linux,三分钟带你揭开Linux过程内幕
  9. Go打印函数名/文件名/行号
  10. 计算机软件实习项目四 —— 校园一卡通管理系统 (代码实现) 12-27
  11. vs2019MSDN(离线帮助文档)的下载与使用
  12. C++ 正则获取url中参数
  13. robotium android,Robotium 测试Android apk安装包
  14. linux命令scp(复制文件和目录)详解及cp和scp命令的使用方法
  15. debian 安装php7_Ubuntu/Debian安装PHP 7.2教程
  16. 电脑饥荒服务器未响应,《饥荒》联机版常见问题及解决方法一览
  17. js中事件加载完成之前添加蒙版
  18. FA-Oracle ERP 资产模块的非常规功能探讨
  19. 机器学习系列(三)——目标函数、损失函数以及代价函数
  20. 通达信标记符号_通达信指标中赋值符号“:”、“=”、“:=”区别?

热门文章

  1. Opera浏览器同步服务被黑,用户数据和存储密码泄露
  2. 【RPC服务器不可用】解决方法
  3. Spring 事务管理高级应用难点剖析
  4. 光驱弹不出来怎么办?光驱弹不出来的简易解决办法。
  5. 专为SaaS而生的PaaS平台!
  6. 祝贺黑龙江馆正式入驻波特城暨龙商龙企龙品走向全球化启动仪式圆满成功
  7. 一场稳定、高清、流畅的大型活动直播是怎么炼成的?
  8. 深入理解 Android Https
  9. 从Java到Kotlin(三)
  10. java 二维码生成和解析