【HDOJ6645】Stay Real(堆)

题意:给定一个n个点的堆,每个点有一个值a[i],每个点必须将在其所有儿子被取之后才能被取

有两个人都按最佳策略行动,问结束之后两人分别取的值之和

n<=1e5,1<=a[i]<=1e9

思路:

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef unsigned int uint;
 5 typedef unsigned long long ull;
 6 typedef pair<int,int> PII;
 7 typedef pair<ll,ll> Pll;
 8 typedef vector<int> VI;
 9 typedef vector<PII> VII;
10 #define N  110000
11 #define M  4100000
12 #define fi first
13 #define se second
14 #define MP make_pair
15 #define pi acos(-1)
16 #define mem(a,b) memset(a,b,sizeof(a))
17 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
18 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
19 #define lowbit(x) x&(-x)
20 #define Rand (rand()*(1<<16)+rand())
21 #define id(x) ((x)<=B?(x):m-n/(x)+1)
22 #define ls p<<1
23 #define rs p<<1|1
24 
25 const ll MOD=998244353,inv2=(MOD+1)/2;
26       double eps=1e-6;
27       int INF=1e9;
28 
29 priority_queue<pair<int,int> > q;
30 
31 ll s[N];
32 int a[N],f[N];
33 
34 int read()
35 {
36    int v=0,f=1;
37    char c=getchar();
38    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
39    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
40    return v*f;
41 }
42 
43 
44 int main()
45 {
46     //freopen("1.in","r",stdin);
47     int cas=read();
48     while(cas--)
49     {
50         int n=read();
51         rep(i,1,n) f[i]=0;
52         rep(i,1,n)
53         {
54             a[i]=read();
55             f[i>>1]++;
56         }
57         rep(i,1,n)
58          if(!f[i]) q.push(MP(a[i],i));
59         s[0]=s[1]=0;
60         int k=0;
61         while(!q.empty())
62         {
63             int u=q.top().se;
64             s[k]+=q.top().fi;
65             q.pop();
66             f[u>>1]--;
67             if(!f[u>>1]) q.push(MP(a[u>>1],u>>1));
68             k^=1;
69         }
70 
71         printf("%I64d %I64d\n",s[0],s[1]);
72     }
73 
74     return 0;
75 }

 

posted on 2019-10-10 20:29  myx12345  阅读(162)  评论(0编辑  收藏  举报

导航