标签:
#139. 【UER #4】被删除的黑白树
Time Limit: 1 Sec
Memory Limit: 256 MB
http://uoj.ac/problem/139
7
1 2
1 3
2 4
2 5
3 6
3 7
Sample Output
7
题意
题解:
首先贪心一下,对于每条从叶子到根节点的黑色棋子个数,应该是最浅的叶子节点的深度
于是我们就可以一次dfs求出这个深度,然后再染色就好了
染色我比较麻烦,我是用dfs序维护的……
每次从叶子节点往上染色,先查询一下这个点的祖先已经染了多少个点,然后再慢慢跑的
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<vector> #include<algorithm> #include<cstring> using namespace std; typedef long long LL; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) #define maxn 300005 vector<int> G[maxn]; vector<int> P; int n; struct PPP { int l,d,r; }node[maxn]; struct Node { int lft,rht; LL sum,add; int mid(){return MID(lft,rht);} void fun(LL tmp) { add+=tmp; sum+=(rht-lft+1)*tmp; } }; int y[maxn]; struct Segtree { Node tree[maxn*4]; void relax(int ind) { if(tree[ind].add) { tree[LL(ind)].fun(tree[ind].add); tree[RR(ind)].fun(tree[ind].add); tree[ind].add=0; } } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].sum=0; tree[ind].add=0; if(lft==rht) tree[ind].sum=y[lft]; else { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } void updata(int st,int ed,int ind,int add) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) tree[ind].fun(add); else { relax(ind); int mid=tree[ind].mid(); if(st<=mid) updata(st,ed,LL(ind),add); if(ed> mid) updata(st,ed,RR(ind),add); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } LL query(int st,int ed,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) return tree[ind].sum; else { relax(ind); int mid=tree[ind].mid(); LL sum1=0,sum2=0; if(st<=mid) sum1=query(st,ed,LL(ind)); if(ed> mid) sum2=query(st,ed,RR(ind)); return sum1+sum2; } } }seg; int cnt = 1; int cntt = 1; int ans = 9999999; bool cmp(int a,int b) { return node[a].d<node[b].d; } void dfs3(int x,int fa,int d) { node[x].l=cntt++; node[x].d=d; for(int i=0;i<G[x].size();i++) { if(G[x][i]==fa) continue; dfs3(G[x][i],x,d+1); } node[x].r=cntt; } void dfs(int x,int pre,int add) { if(G[x].size()==1&&x!=1) { P.push_back(x); ans = min(ans,add); return; } for(int i=0;i<G[x].size();i++) { int v=G[x][i]; if(v==pre)continue; dfs(v,x,add+1); } } int Ans = 0; int vis[maxn]; void dfs2(int x,int pre,int add) { if(vis[x])return; if(add<=0)return; vis[x]=1; Ans++; seg.updata(node[x].l,node[x].r-1,1,1); for(int i=0;i<G[x].size();i++) { int v = G[x][i]; if(v==pre)continue; if(node[v].d >= node[x].d)continue; dfs2(v,x,add-1); } } int main() { //freopen("k.in","r",stdin); //freopen("2.out","w",stdout); scanf("%d",&n); if(n==1) { printf("1\n");return 0; } for(int i=1;i<n;i++) { int x,y;scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } seg.build(1,n,1); dfs(1,-1,1); dfs3(1,-1,1); sort(P.begin(),P.end(),cmp); for(int i=0;i<P.size();i++) { int t = 0; int xx = seg.query(node[P[i]].l,node[P[i]].l,1); if(xx<0)continue; if(P[i]!=1) t = ans-xx; dfs2(P[i],-1,t); } printf("%d\n",Ans); }
uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心
标签:
原文地址:http://www.cnblogs.com/qscqesze/p/4906634.html