hdu5242 Game (贪心+dfs序)
dfs序后用线段树来记每个节点的前缀和
每次找一个前缀和最大的节点,然后把它到根的路径上的每个之前没被走过的点 对应的dfs序的区间 减掉那个点的权值
每个点最多被减一次,复杂度是$O(nlogn)$的
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e5+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int eg[maxn][2],egh[maxn],ect,root,fa[maxn]; 16 int N,K,ch[maxn][2],pct,dfn[maxn][2],tot,id[maxn]; 17 ll v[maxn],dis[maxn],ma[maxn],mi[maxn]; 18 ll laz[maxn]; 19 bool flag[maxn]; 20 21 inline void adeg(int a,int b){ 22 eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect; 23 } 24 25 void dfs(int x){ 26 dfn[x][0]=++tot,id[tot]=x; 27 28 for(int i=egh[x];i;i=eg[i][1]){ 29 int b=eg[i][0];if(b==fa[x]) continue; 30 fa[b]=x;dis[b]=dis[x]+v[b]; 31 dfs(b); 32 } 33 dfn[x][1]=tot; 34 } 35 36 inline void update(int p){ 37 if(!ch[p][0]) return; 38 if(ma[ch[p][0]]>ma[ch[p][1]]) ma[p]=ma[ch[p][0]],mi[p]=mi[ch[p][0]]; 39 else ma[p]=ma[ch[p][1]],mi[p]=mi[ch[p][1]]; 40 } 41 inline void pushdown(int p){ 42 if(!laz[p]||!ch[p][0]) return; 43 ma[ch[p][0]]+=laz[p],ma[ch[p][1]]+=laz[p]; 44 laz[ch[p][0]]+=laz[p],laz[ch[p][1]]+=laz[p]; 45 laz[p]=0; 46 } 47 48 void build(int &p,int l,int r){ 49 p=++pct; 50 if(l==r) ma[p]=dis[id[l]],mi[p]=id[l]; 51 else{ 52 int m=l+r>>1; 53 build(ch[p][0],l,m);build(ch[p][1],m+1,r); 54 update(p); 55 } 56 } 57 58 void add(int p,int l,int r,int x,int y,ll z){ 59 pushdown(p); 60 if(x<=l&&r<=y){ 61 laz[p]+=z;ma[p]+=z; 62 pushdown(p); 63 }else{ 64 int m=l+r>>1; 65 if(x<=m) add(ch[p][0],l,m,x,y,z); 66 if(y>=m+1) add(ch[p][1],m+1,r,x,y,z); 67 update(p); 68 } 69 } 70 71 int main(){ 72 //freopen("","r",stdin); 73 int i,j,k; 74 int T=rd(); 75 for(int tt=1;tt<=T;tt++){ 76 N=rd(),K=rd(); 77 CLR(ch,0);CLR(egh,0);CLR(laz,0);ect=pct=tot=root=0; 78 CLR(dis,0);CLR(flag,0); 79 for(i=1;i<=N;i++) v[i]=rd(); 80 for(i=1;i<N;i++){ 81 int a=rd(),b=rd(); 82 adeg(a,b); 83 } 84 dis[1]=v[1];dfs(1); 85 build(root,1,N); 86 ll ans=0; 87 for(i=1;i<=K;i++){ 88 ans+=ma[root];int ii=mi[root]; 89 // printf("!%lld %d\n",ma[root],mi[root]); 90 while(ii&&!flag[ii]){ 91 add(root,1,N,dfn[ii][0],dfn[ii][1],-v[ii]); 92 // printf("--%d %d %d\n",dfn[ii][0],dfn[ii][1],v[ii]); 93 flag[ii]=1;ii=fa[ii]; 94 } 95 } 96 printf("Case #%d: %lld\n",tt,ans); 97 } 98 return 0; 99 }