codeforces533A Berland Miners -- 線段樹
阿新 • • 發佈:2019-02-16
離散。先求出每個點到根路徑上
開一個桶,將每個
那麼只有當所有後綴和不小於
如果要增加一個點的高度,先從大到小列舉桶中的元素,找到第一個小於
用線段樹維護字尾和的最小值,列舉這個點,更新線段樹,如果滿足條件就更新答案。
怎麼更新線段樹呢?容易看出更新一個點只會影響若干條鏈,區間加就可以了。
具體可以看程式碼。
程式碼:
#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 1e9
struct 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;
}