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 ...
随机推荐
- P1048 采药
题目描述 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个 ...
- ORM优化
orm优化数据库访问:https://docs.djangoproject.com/en/1.11/topics/db/optimization/ 一.QuerySet 可迭代 querysey=mo ...
- Just a Hook (HDU 1698) 懒惰标记
Just a Hook (HDU 1698) 题链 每一次都将一个区间整体进行修改,需要用到懒惰标记,懒惰标记的核心在于在查询前才更新,比如将当前点rt标记为col[rt],那么此点的左孩子和右孩子标 ...
- [bzoj3671][Noi2014][随机数生成器] (贪心+位运算+卡空间)
Description Input 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M ...
- Python异常捕捉的一个小问题
问题: names = ['taotao','songwenjing','liu','li']I = iter(names)while True: try: s = next(I) except Ex ...
- 【hdu 1043】Eight
[题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=1043 [题意] 会给你很多组数据; 让你输出这组数据到目标状态的具体步骤; [题解] 从12345 ...
- Apache 流框架 Flink,Spark Streaming,Storm对比分析(2)
此文已由作者岳猛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2.Spark Streaming架构及特性分析 2.1 基本架构 基于是spark core的spark s ...
- HDU 1561 树形DP背包问题
这是自己第一道背包上树形结构问题,不是很理解这个概念的可以先看看背包九讲 自己第一次做,看了一下别人的思路,结合着对简单背包问题的求解方式自己一次AC了还是有点小激动的 题目大意是: 攻克m个城市,每 ...
- 后台获得集合,变成json字符串,放到EL表达式,js进行获取遍历
//把集合编程json字符串,放到el表达式 JSONArray array = new JSONArray(); JSONArray fromObject = array.fromObject(ar ...
- 【Eclipse】Eclipse 快捷键
Eclipse 快捷键 关于快捷键 Eclipse 的很多操作都提供了快捷键功能,我们可以通过键盘就能很好的控制 Eclipse 各个功能: 使用快捷键关联菜单或菜单项 使用快捷键关联对话窗口或视图或 ...