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;
}
全部评论

相关推荐

粗心的雪碧不放弃:纯学历问题,我这几个月也是一直优化自己的简历,后来发现优化到我自己都觉得牛逼的时候,发现面试数量也没有提升,真就纯学历问题
点赞 评论 收藏
分享
11-11 14:21
西京学院 C++
Java抽象练习生:教育背景放最前面,不要耍小聪明
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务