codeforces533A Berland Miners -- 线段树
来源:互联网 发布:国际顶级域名com 编辑:程序博客网 时间:2024/06/05 16:08
离散。先求出每个点到根路径上
开一个桶,将每个
那么只有当所有后缀和不小于
如果要增加一个点的高度,先从大到小枚举桶中的元素,找到第一个小于
用线段树维护后缀和的最小值,枚举这个点,更新线段树,如果满足条件就更新答案。
怎么更新线段树呢?容易看出更新一个点只会影响若干条链,区间加就可以了。
具体可以看代码。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<vector>using namespace std;inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if(p1==p2){ p2=(p1=buf)+fread(buf,1,100000,stdin); if(p1==p2)return EOF; } return *p1++;}inline void Read(int& x){ char c=nc(); for(;c<'0'||c>'9';c=nc()); for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}#define N 500010#define INF 1e9struct Edge{ int t,nx;}e[N<<1];struct Node{ int f,w;}L[N<<1];vector<int>g[N];int i,j,k,n,m,x,y,Cnt,M,h[N],t[N<<1],c[N<<2],p[N<<2],c1[N],c2[N],a[N],b[N],w[N<<1],l,r,Ans=INF,f[N];inline int Min(int x,int y){ return x<y?x:y;}inline bool Cmp(int x,int y){ return x>y;}inline bool Cmp1(Node x,Node y){ return x.w<y.w;}inline void Add(int x,int y){ e[++Cnt].t=y;e[Cnt].nx=h[x];h[x]=Cnt;}inline void Dfs(int x,int y){ if(a[x]<=a[c1[y]])c1[x]=x,c2[x]=c1[y];else if(a[x]<a[c2[y]])c1[x]=c1[y],c2[x]=x;else c1[x]=c1[y],c2[x]=c2[y]; for(int i=h[x];i;i=e[i].nx) if(e[i].t!=y)Dfs(e[i].t,x);}inline int Find(int x){ int l=1,r=m,Mid,Ans=1; while(l<=r){ Mid=l+r>>1; if(b[Mid]>x)Ans=Mid,l=Mid+1;else r=Mid-1; } return Ans;}inline void Down(int x){ c[x<<1]+=p[x]; p[x<<1]+=p[x]; c[x<<1|1]+=p[x]; p[x<<1|1]+=p[x]; p[x]=0;}inline void Build(int x,int l,int r){ if(l==r){ c[x]=t[l]; return; } int Mid=l+r>>1; Build(x<<1,l,Mid); Build(x<<1|1,Mid+1,r); c[x]=Min(c[x<<1],c[x<<1|1]);}inline void Update(int x,int l,int r,int L,int R,int y){ if(l>R||r<L)return; if(l>=L&&r<=R){ c[x]+=y; p[x]+=y; return; } if(p[x])Down(x); int Mid=l+r>>1; Update(x<<1,l,Mid,L,R,y); Update(x<<1|1,Mid+1,r,L,R,y); c[x]=Min(c[x<<1],c[x<<1|1]);}int main(){ Read(n); for(i=1;i<=n;i++)Read(L[i].w),L[i].f=i; for(i=1;i<n;i++)Read(x),Read(y),Add(x,y),Add(y,x); Read(m); for(i=1;i<=m;i++)Read(L[n+i].w),L[n+i].f=n+i; sort(L+1,L+n+m+1,Cmp1); if(L[1].f>n)b[L[1].f-n]=M=1;else a[L[1].f]=M=1;w[1]=L[1].w; for(i=2;i<=n+m;i++) if(L[i].w==L[i-1].w)if(L[i].f>n)b[L[i].f-n]=M;else a[L[i].f]=M;else{ w[++M]=L[i].w; if(L[i].f>n)b[L[i].f-n]=M;else a[L[i].f]=M; } sort(b+1,b+m+1,Cmp); a[0]=INF; Dfs(1,0); for(i=1;i<=n;i++)t[a[c1[i]]]++; for(i=1;i<=m;i++)t[b[i]]--; for(i=M-1;i;i--)t[i]+=t[i+1]; for(k=M;k;k--)if(t[k]<0)break; if(!k){ printf("0\n"); return 0; } Build(1,1,M); for(i=1;i<=n;i++) g[c1[i]].push_back(Min(a[c2[i]],k)); for(i=1;i<=n;i++) if(a[i]<k){ for(j=0;j<g[i].size();j++) if(a[i]+1<=g[i][j])Update(1,1,M,a[i]+1,g[i][j],1); if(c[1]>=0)Ans=Min(Ans,w[k]-w[a[i]]); for(j=0;j<g[i].size();j++) if(a[i]+1<=g[i][j])Update(1,1,M,a[i]+1,g[i][j],-1); } if(Ans==INF)printf("-1\n");else printf("%d\n",Ans); return 0;}
阅读全文
0 0
- codeforces533A Berland Miners -- 线段树
- 【codechef】Ancient Berland Roads(线段树)
- Berland Flag
- [BZOJ1806][Ioi2007]Miners 矿工配餐
- BZOJ1806: [Ioi2007]Miners 矿工配餐
- BZOJ1806: [Ioi2007]Miners 矿工配餐
- bzoj1806 [Ioi2007]Miners 矿工配餐
- bzoj1806[ioi2007]Miners 矿工配餐
- BZOJ1806: [Ioi2007]Miners 矿工配餐
- bzoj1806 [Ioi2007]Miners 矿工配餐
- bzoj1806: [Ioi2007]Miners 矿工配餐
- 1806: [Ioi2007]Miners 矿工配餐
- 1806: [Ioi2007]Miners 矿工配餐
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- bzoj1806:[Ioi2007]Miners 矿工配餐 [多维DP]
- 浏览OSG自带的例子
- [华为机试题]简单错误记录
- PhotoshopCS6学习笔记
- B2Ctt商城07 redis
- 模型拟合的解析方法
- codeforces533A Berland Miners -- 线段树
- 新建user账户之后无法登录 提示error 1045(28000)解决步骤
- Linux C语言编程(3)——文件系统实验
- 《Hadoop生态》——第二章 数据库与数据管理——Accumulo
- 简单的Linux下的socket程序
- kafka 问题
- 关于javascript代码调试问题
- Codeforces 822 D. My pretty girl Noora(多项式加法+dp)
- linux下调用opencv接口函数处理输入文本和字体