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 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9758906.html