CF1099F Cookies
本题解同步发布于[本场总题解](https://www.luogu.org/blog/expect2004/CF530Div2),欢迎来踩。
F - Cookies
这题在考试时间内有了正确的思路但没有写完。。。
的策略
题目的表述中,是可以随便剪断当前标记所在结点到任意一棵子树的。
但是题目要求我们求的是最坏情况下的最小值,我们可以只考虑创造了最坏的条件,即剪掉了本来可以取到最优解的子树。
树形
首先做一次,求出不剪时的最优解,同时记录取到最优解的位置。
接下来标记不得进入之前最优解的位置,再做一次。
这两次等价于维护了每个结点的最优解和次优解。
在的过程中使用了贪心的思想,显然从根到的路径上,尽量吃花费时间少的饼干。
维护饼干
我一开始是想通过或者来维护的,可是发现这样不太好实现,并且在链的情况下复杂度会退化为。
我太菜了并不会多少数据结构,于是自然而然想到使用树状数组来维护,树状数组的下标为,插入的值为饼干数目。
然后二分就行了。
code:
#include<bits/stdc++.h> using namespace std; #define int long long #define maxn 100003 int n,T; int x[maxn],t[maxn]; int Head[maxn],tot,Next[maxn],to[maxn],w[maxn]; int aa,bb; int ans[maxn]; int fake; template<typename Tp> void read(Tp &x){ x=0;char ch=1;int fh; while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar(); if(ch=='-'){ ch=getchar();fh=-1; } else fh=1; while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+ch-'0'; ch=getchar(); } x*=fh; } struct BIT{ #define lowbit(x) (x&(-x)) int c[1001003]; void add(int x,int k){ while(x<=1001000){ c[x]+=k;x+=lowbit(x); } } int query(int x){ int re=0; while(x){ re+=c[x];x-=lowbit(x); } return re; } }a,b; void add(int x,int y,int z){ to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z; } int erfen(int fa){ int l=0,r=1000000,mid,re=0; while(l<=r){ mid=(l+r)>>1; if(a.query(mid)<=fa) re=mid,l=mid+1; else r=mid-1; } fake=l; return re; } int find(int node){ int l=fake,r=1000000,re=0,mid; while(l<=r){ mid=(l+r)>>1; if(b.query(mid)!=ans[node]) re=mid,r=mid-1; else l=mid+1; } return re; } void dfs(int node,int dis){ int rest=T-2*dis; a.add(t[node],x[node]*t[node]); b.add(t[node],x[node]); int flag=erfen(rest); if(flag) ans[node]=b.query(flag),rest-=a.query(flag); flag=find(node); if(flag) ans[node]+=rest/flag; for(int i=Head[node];i;i=Next[i]){ dfs(to[i],dis+w[i]); } a.add(t[node],-x[node]*t[node]); b.add(t[node],-x[node]); int mx=0,del=0; for(int i=Head[node];i;i=Next[i]){ if(ans[to[i]]>mx){ mx=ans[to[i]],del=to[i]; } } if(node==1){ ans[node]=max(ans[node],mx); return; } for(int i=Head[node];i;i=Next[i]){ if(to[i]==del) continue; ans[node]=max(ans[node],ans[to[i]]); } } int main(){ read(n);read(T); for(register int i=1;i<=n;i++){ read(x[i]); } for(register int i=1;i<=n;i++){ read(t[i]); } for(register int i=2;i<=n;i++){ read(aa);read(bb); add(aa,i,bb); } dfs(1,0); printf("%I64d\n",ans[1]); return 0; }