Gym - 101972B Arabella Collegiate Programming Contest (2018) B. Updating the Tree 树DFS
题意: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,所以在使用后,马上进行了清空,代码有点冗余
#include<bits/stdc++.h>
using namespace std;
#define N 100007
int n,v[N],siz[N],de[N],vis[N],T,u,w;
vector<int> g[N];
int now,cnt1[][N*],mx1[],cnt2[][N*],mx2[];
int nod[][N],tot[],ad[N*],mxx,ans[N];
bool dfs(int x,int dep)
{
vis[x]=;
siz[x]=;
de[x]=dep;
bool re=;
int cnt=;
for(int i=;i<g[x].size();i++)
if(!vis[g[x][i]])
{
if(cnt != )
{
now^=;
mx1[now]=mx2[now]=;
for(int j=;j<=tot[now];j++)
{
int xx=nod[now][j];
cnt1[now][v[xx]-de[xx]]=;
cnt2[now][v[xx]+de[xx]]=;
}
tot[now]=;
}
re&=dfs(g[x][i],dep+),siz[x]+=siz[g[x][i]];
cnt++;
}
if(!re || g[x].size()> || (x== && g[x].size()==))
{
ans[x]=-;
return ;
}
if(g[x].size()== || (x== && g[x].size()==))
{
int tmp = ;
mxx = ;
for(int i = ; i <= tot[now]; i++)
{
int xx = nod[now][i];
ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++;
}
ad[v[x] - tmp]++; mxx = max(mxx, ad[v[x] - tmp]); tmp++;
for(int i = tot[now ^ ]; i >= ; i--)
{
int xx = nod[now ^ ][i];
ad[v[xx] - tmp]++; mxx = max(mxx, ad[v[xx] - tmp]); tmp++;
}
ans[x] = siz[x] - mxx; tmp = ;
for(int i = ; i <= tot[now]; i++)
{
int xx = nod[now][i];
ad[v[xx] - tmp]--; tmp++;
}
ad[v[x] - tmp]--; tmp++;
for(int i = tot[now ^ ]; i >= ; i--)
{
int xx = nod[now ^ ][i];
ad[v[xx] - tmp]--; tmp++;
} tmp = ;
mxx = ;
for(int i = ; i <= tot[now]; i++)
{
int xx = nod[now][i];
ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++;
}
ad[v[x] + tmp]++; mxx = max(mxx, ad[v[x] + tmp]); tmp++;
for(int i = tot[now ^ ]; i >= ; i--)
{
int xx = nod[now ^ ][i];
ad[v[xx] + tmp]++; mxx = max(mxx, ad[v[xx] + tmp]); tmp++;
}
ans[x] = min(ans[x], siz[x] - mxx);
tmp = ;
for(int i = ; i <= tot[now]; i++)
{
int xx = nod[now][i];
ad[v[xx] + tmp]--; tmp++;
}
ad[v[x] + tmp]--; tmp++;
for(int i = tot[now ^ ]; i >= ; i--)
{
int xx=nod[now^][i];
ad[v[xx]+tmp]--;tmp++;
}
return ;
}
nod[now][++tot[now]]=x;
cnt1[now][v[x]-dep]++;
if(cnt1[now][v[x]-dep]>mx1[now]) mx1[now]=cnt1[now][v[x]-dep];
cnt2[now][v[x]+dep]++;
if(cnt2[now][v[x]+dep]>mx2[now]) mx2[now]=cnt2[now][v[x]+dep];
ans[x]=siz[x]-max(mx1[now], mx2[now]);
return ;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
now=;
mx1[now]=mx2[now]=;
for(int j=;j<=tot[now];j++)
{
int xx=nod[now][j];
cnt1[now][v[xx]-de[xx]]=;
cnt2[now][v[xx]+de[xx]]=;
}
tot[now]=;
now=;
mx1[now]=mx2[now]=;
for(int j=;j<=tot[now];j++)
{
int xx=nod[now][j];
cnt1[now][v[xx]-de[xx]]=;
cnt2[now][v[xx]+de[xx]]=;
}
tot[now] = ;
now = ;
for(int i=;i<=n;i++) vis[i]=,ans[i]=;
for(int i=;i<=n;i++) g[i].clear();
for(int i=;i<=n;i++) scanf("%d",&v[i]),v[i]+=;
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&w);
g[u].push_back(w);
g[w].push_back(u);
}
dfs(,);
for(int i = ; i <= n; i++) printf("%d ", ans[i]);
puts("");
}
}
不挤在一次dfs里好像就短多了
#include<bits/stdc++.h>
#define lld long long
#define N 300007
using namespace std;
int T,n,nn,pn,u,w;
int v[N],dep[N],fa[N],dp[N],dq[N];
int ch[N],ok[N],p[N],ans[N],sz[N];
vector<int> g[N];
void DFS(int x)
{
for (auto e: g[x]) if (e!=fa[x]) DFS(e);
p[pn++]=x;
}
void work(int id)
{
int t;
for (int i=;i<pn;i++)
{
if (id==-) t=p[i];else t=id;
ans[t]=max(ans[t],++dq[v[p[i]]+i]);
ans[t]=max(ans[t],++dp[v[p[i]]-i]);
if (i && id==-) ans[p[i]]=max(ans[p[i]],ans[p[i-]]);
}
for (int i=;i<pn;i++)
{
dp[v[p[i]]-i]--;
dq[v[p[i]]+i]--;
}
}
void solve(int x)
{
pn=;
DFS(x);
work(-);
}
void solve2(int x)
{
pn=;
int tn=-;
for (auto e: g[x]) if (e!=fa[x])
{
DFS(e);
if (tn==-)
{
p[pn++]=x;
tn=pn;
}
}
reverse(p+tn,p+pn);
work(x);
}
void dfs(int x)
{
ok[x]=sz[x]=;
ch[x]=;
for (auto e:g[x]) if (e!=fa[x])
{
ch[x]++;
fa[e]=x;
dfs(e);
sz[x]+=sz[e];
ok[x]&=ok[e];
}
ok[x]&=ch[x]<=;
if (!ok[x])
{
for (auto e:g[x]) if (e!=fa[x] && ok[e]) solve(e);
if (ch[x]==)
{
int c=;
for (auto e:g[x]) if (e!=fa[x] && ok[e]) c++;
if (c==) solve2(x);
}
}
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=;i<n;i++)
{
g[i].clear();
scanf("%d",&v[i]);
v[i]+=n;
ans[i]=-;
}
for (int i=;i<n;i++)
{
scanf("%d%d",&u,&w);
u--;w--;
g[u].emplace_back(w);
g[w].emplace_back(u);
}
fa[]=-;
dfs();
if (ok[]) solve();
for (int i=;i<n;i++) printf("%d ",ans[i]==-?-:sz[i]-ans[i]);
puts("");
}
}
Gym - 101972B Arabella Collegiate Programming Contest (2018) B. Updating the Tree 树DFS的更多相关文章
- ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018
ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syr ...
- German Collegiate Programming Contest 2018 B. Battle Royale
Battle Royale games are the current trend in video games and Gamers Concealed Punching Circles (GCPC ...
- German Collegiate Programming Contest 2018 C. Coolest Ski Route
John loves winter. Every skiing season he goes heli-skiing with his friends. To do so, they rent a h ...
- 边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H
http://codeforces.com/gym/100676/attachments 题目大意: 有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送 ...
- Gym - 101810H ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...
- Gym - 101810F ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include<bits/stdc++.h> using namespace std; #def ...
- Gym - 101810E ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include<bits/stdc++.h> using namespace std; #def ...
- Gym - 101810D ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...
- Gym - 101810C ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...
随机推荐
- [Python数据结构] 使用List实现Stack
[Python数据结构] 使用List实现Stack 1. Stack 堆栈(Stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型(ADT),其特殊之处在于只能允许在阵列的一端进 ...
- idea搭建maven项目 【转发】
为了创建maven项目可是花了我时间了,网上的教程跟我的实际情况不符合,尤其是facets .artifacts 那块.幸亏找到这篇文章没解决了我的问题,他的描述跟我的情况一模一样.这篇文章竟然来自百 ...
- CF2B The least round way
[题解] 可以发现10的因数除了1和10之外只有2和5了,那么走过的路径上各个数字的2的因数个数之和.5的因数个数之和中较小的一个即是答案.这样的话DP即可.同时需要注意有0的情况,有0的时候有一个答 ...
- POJ 1226 Substrings
Substrings Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. Original ID: ...
- 转载 - Python里面关于 模块 和 包 和 __init__.py 的一些事
出处:http://www.cnblogs.com/tqsummer/archive/2011/01/24/1943273.html python中的Module是比较重要的概念.常见的情况是,事先写 ...
- jquery追加元素的几种方法(append()、prepend()、after()、before()、insertAfter()、insertBefore())
最近项目不是很忙,抽空整理了下,js中常用追加元素的几种方法. <!DOCTYPE html> <html> <head> <meta charset=&qu ...
- js中防止输入为空,或者为字母
function checkNum(){ var num1=document.getElementById("num1").value; var num2=document.get ...
- CodeForces 362C
分析:首先我们要知道调用swap()函数的次数跟什么有关.可以观察发现在Insertion Sort里,当且仅当a[j](j∈[0,i)) > a[i]时会调用一次swap(),也就是说有多少个 ...
- 交友app
编辑注记:这是由译者 han_qi 翻译纽约客的一篇文章,从女性的角度描写了交友产品的用户体验及需求,值得广大产品经理深入研究,文章略长,但值得深读.原文<Overwhelmed and Cre ...
- 从理论到实践,全方位认识DNS(实践篇)
在理论篇中,我们基本了解了DNS的整个协议原理,但是可能还会有着下面的疑问: 为什么我想申请的域名都没了? DNS 域名还要备案,这是为什么啊? 如何将刚申请的域名绑定到自己的网站呢? 怎么才能看到那 ...