Codeforces 1099F Cookies
给一棵树,边权为时间花费,每个节点有t[i]表示在这个节点吃一个cookie花的时间,x[i]表示这个节点cookie的个数,给了限制时间T
A先手移动从根节点,每次移动到子节点或者返回,返回途中吃cookie
B后手可以选择阻止A到达某个子节点
问可以吃到的最大的数量
假设到达点u后开始返回,即用T-边权和的时间尽可能的多吃,可以以这条到根的链上的t为下标建立线段树,二分贪心询问最大的数量
其次是考虑有B的限制问题,所以可以求dp,表示从u点的最优决策值
首先是从u返回的值
其次是在u的子节点里选择继承,但是因为B的限制要选次大值(除了根节点,因为先手)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 const int MAXN=1e6+17; 5 const int lim=1e6; 6 LL T; 7 int n; 8 int x[MAXN],t[MAXN]; 9 vector<pair<int ,int > >to[MAXN]; 10 struct segment_tree{ 11 #define ls (u<<1) 12 #define rs (u<<1|1) 13 LL num[MAXN<<2],sm[MAXN<<2]; 14 void up(int u){ 15 num[u]=num[ls]+num[rs]; 16 sm[u]=sm[ls]+sm[rs]; 17 return ; 18 } 19 void build(int u,int l,int r){ 20 sm[u]=num[u]=0; 21 if(l==r)return ; 22 int mid=l+r>>1; 23 build(ls,l,mid),build(rs,mid+1,r); 24 return up(u); 25 } 26 LL query(int u,int l,int r,LL ssm){ 27 if(sm[u]==0)return 0; 28 // cout<<u<<" "<<l<<" "<<r<<" "<<ssm<<" "<<sm[ls]<<" "<<sm[rs]<<endl; 29 if(l==r)return min(ssm/l,num[u]); 30 int mid=l+r>>1; 31 if(sm[ls]>=ssm)return query(ls,l,mid,ssm); 32 else return num[ls]+query(rs,mid+1,r,ssm-sm[ls]); 33 } 34 void modify(int u,int l,int r,int pos,LL nnm){ 35 // cout<<u<<" "<<l<<" "<<r<<" "<<pos<<" "<<nnm<<endl; 36 if(l==r){ 37 num[u]+=nnm; 38 sm[u]+=nnm*pos; 39 return ; 40 } 41 int mid=l+r>>1; 42 if(pos<=mid)modify(ls,l,mid,pos,nnm); 43 else modify(rs,mid+1,r,pos,nnm); 44 return up(u); 45 } 46 }tr; 47 LL dfs(int u,LL rem){ 48 // cout<<"FSDFDSS "<<u<<" "<<rem<<" "<<t[u]<<" "<<x[u]<<endl; 49 tr.modify(1,1,lim,t[u],x[u]); 50 LL res=tr.query(1,1,lim,rem); 51 // cout<<u<<" "<<res<<endl; 52 LL mx1=0,mx2=0; 53 for(int i=0;i<to[u].size();++i){ 54 pair<int ,int >y=to[u][i]; 55 if(rem-y.second<=0)continue; 56 LL t=dfs(y.first,rem-y.second); 57 if(t>=mx1)mx2=mx1,mx1=t; 58 else if(t>mx2)mx2=t; 59 } 60 61 tr.modify(1,1,lim,t[u],-x[u]); 62 if(u==1)res=max(res,mx1); 63 // cout<<u<<" "<<max(res,mx2)<<" "<<rem<<endl; 64 return max(res,mx2); 65 } 66 int main(){ 67 scanf("%d%lld",&n,&T); 68 tr.build(1,1,lim); 69 for(int i=1;i<=n;++i)scanf("%d",&x[i]); 70 for(int i=1;i<=n;++i)scanf("%d",&t[i]); 71 for(int i=2,p,l;i<=n;++i){ 72 scanf("%d%d",&p,&l); 73 to[p].push_back(make_pair(i,l*2)); 74 } 75 printf("%lld\n",dfs(1,T)); 76 return 0; 77 }