题意:给定一个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 ",s[0],s[1]); 72 } 73 74 return 0; 75 }