CF 1399E2. Weights Division (hard version) (枚举+贪心)

题目链接:传送门

题目思路:题目相对于easy version 添加了一个cost条件,即w[i]/=2,不再是一次move,而是cost[i]次move(cost[i] ==1 or 2 ) 。 根据easy version贪心的思想,可以对于cost=1 和 cost=2 的两种边分别构造一个最优的move序列(可以得到当前最大的贡献值),然后枚举cost=1 的move 次数得到总贡献值,然后二分cost = 2 的move序列即可。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long LL;
  4 typedef pair<int,int> pii;
  5 typedef pair<LL,LL> pLL;
  6 #define pb push_back
  7 #define mk make_pair
  8 #define fi first
  9 #define se second
 10 #define mem(a,b) memset(a,b,sizeof(a))
 11 const int N=4e6+5;
 12 const int inf=0x3f3f3f3f;
 13 LL read()
 14 {
 15     LL x=0,f=1;
 16     char ch=getchar();
 17     while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); }
 18     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
 19     return f*x;
 20 }
 21 struct edge
 22 {
 23     int v,w,c;
 24     edge(){}
 25     edge(int vv,int ww,int cc){ v=vv; w=ww; c=cc; }
 26 };
 27 vector<edge> e[N];
 28 struct node{
 29     LL x,id;
 30     node(){}
 31     node(LL xx,LL ii){ x=xx; id=ii; }
 32     friend bool operator < (node X,node Y)
 33     {
 34         return X.x<Y.x;
 35     }
 36 };
 37 priority_queue<node> q1,q2;
 38 LL cnt[N],w[N],n,s,s1[N],s2[N],c[N];
 39 void dfs(int u,int pre)
 40 {
 41     if(e[u].size()>1) cnt[u]=0;
 42     else cnt[u]=1;
 43     for(int i=0;i<e[u].size();i++)
 44     {
 45         edge x=e[u][i];
 46         int v=x.v;
 47         if(v==pre) continue;
 48         dfs(v,u);
 49         w[v]=x.w;
 50         c[v]=x.c;
 51         cnt[u]+=cnt[v];
 52     }
 53 }
 54 void init()
 55 {
 56     for(int i=1;i<=n;i++) e[i].clear();
 57     while(!q1.empty()) q1.pop();
 58     while(!q2.empty()) q2.pop();
 59 }
 60 int main()
 61 {
 62     int T=read();
 63     while(T--)
 64     {
 65         init();
 66         n=read(),s=read();
 67         for(int i=1;i<n;i++)
 68         {
 69             int x=read(),y=read(),z=read(),k=read();
 70             e[x].pb(edge(y,z,k));
 71             e[y].pb(edge(x,z,k));
 72         }
 73         dfs(1,0);
 74         LL res=0;
 75         for(int i=2;i<=n;i++)
 76             res+=1LL*w[i]*cnt[i];
 77         for(int i=2;i<=n;i++)
 78             if(c[i]==1) q1.push(node(1LL*cnt[i]*(w[i]-w[i]/2),i));
 79             else q2.push(node(1LL*cnt[i]*(w[i]-w[i]/2),i));
 80         int t1=0,t2=0;
 81         LL tmp=0;
 82         while(!q1.empty())
 83         {
 84             node t=q1.top();
 85             q1.pop();
 86             tmp+=t.x;
 87             s1[++t1]=tmp;
 88             w[t.id]/=2;
 89             if(w[t.id]) q1.push(node(1LL*cnt[t.id]*(w[t.id]-w[t.id]/2),t.id));
 90         }
 91         tmp=0;
 92         while(!q2.empty())
 93         {
 94             node t=q2.top();
 95             q2.pop();
 96             tmp+=t.x;
 97             s2[++t2]=tmp;
 98             w[t.id]/=2;
 99             if(w[t.id]) q2.push(node(1LL*cnt[t.id]*(w[t.id]-w[t.id]/2),t.id));
100         }
101 
102         int ans=inf;
103         res-=s;
104         /*
105         printf("res = %lld\n",res);
106         printf("s1: "); for(int i=0;i<=t1;i++) printf("%lld%c",s1[i],i==t1?'\n':' ');
107         printf("s2: "); for(int i=0;i<=t2;i++) printf("%lld%c",s2[i],i==t2?'\n':' ');
108         */
109         for(int i=0;i<=t1;i++)
110         {
111             LL x=res-s1[i];
112             int j=lower_bound(s2,s2+t2+1,x)-s2;
113             if(j>t2) continue;
114             ans=min(ans,i+2*j);
115         }
116         printf("%d\n",ans);
117     }
118     return 0;
119 }
View Code

 

posted @ 2020-09-08 18:34  DeepJay  阅读(169)  评论(0编辑  收藏  举报