Codeforces Round 1107 (Div. 3)D&&E

D

思路:肯定是一个一个操作或者两个两个操作最优,对于ai<bi的这种情况很好办直接加就行,难点在于ai>bi的这种情况,这种情况不好办,那么ai<bi可以看成这个点的价值,可以对右边产生贡献例如:

1 3 4

5 3 1

我可以先:

1 0 4

2 0 4

再:

1 3 4

2 3 4

最后给1加上1就行了,

所以这个ai<bi这个差值是可以向右一直移动的,

为了模拟,我们令now初始=0,遇到ai<bi则+1,遇到ai>bi就减少,如果不够这个减就说明方案不可行输出no

代码:

cpp 复制代码
void solve(){
    int n;cin>>n;
    vector<int>a(n+10),b(n+10);
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    int now=0;
    for(int i=1;i<=n;i++){
        if(a[i]<=b[i]){
            now+=b[i]-a[i];
        }
        else{
            if(now<a[i]-b[i]){
                cout<<"NO"<<endl;
                return;
            }
            now-=(a[i]-b[i]);
        }
    }
    cout<<"YES"<<endl;
}

E

思路:

u v w

观察样例发现,中间的节点要被乘三次,所以中间节点是完全平方数,对中间节点进行操作,可知,有两种贡献方式,一种是中间节点是u,v,w其中一个,一种是不是,对应了选2还是3个"儿子":

选两个:

cpp 复制代码
int s2=0;
            int k=son.size()-1;
            vector<int>cnt2(k+10);
            for(int i=1;i<=k;i++){
                cnt2[i]=son[i]*(s-son[i]);
                s2+=cnt2[i];
            }
            s2/=2;

选三个:

cpp 复制代码
 int s3=0;
            for(int i=1;i<=k;i++){
                s3+=son[i]*(s2-cnt2[i]);
            }
            s3/=3;
            ans+=s2+s3;

代码:

cpp 复制代码
void solve(){
    int n;cin>>n;
    vector<int>a(n+10);
    for(int i=1;i<=n;i++) cin>>a[i];
    vector<vector<int> >g(n+10);
    for(int i=1;i<=n-1;i++){
        int u,v;cin>>u>>v;
        g[u].push_back(v),g[v].push_back(u);
    }
    vector<int>cnt(n+10,1);
    auto dfs=[&](auto &&dfs,int u,int fa)->void{
        for(auto v:g[u]){
            if(v==fa) continue;
            dfs(dfs,v,u);
            cnt[u]+=cnt[v];
        }
    };dfs(dfs,1,-1);
    vector<int>pre(n+10);
    int ans=0;
    auto dfs2=[&](auto &&dfs2,int u,int fa)->void{
        vector<int>son(1);
        int s=0;
        son.push_back(pre[u]);s+=pre[u];
        for(auto v:g[u]){
            if(v==fa) continue;
            pre[v]=pre[u]+cnt[u]-cnt[v];
            dfs2(dfs2,v,u);
            son.push_back(cnt[v]); s+=cnt[v];
        }
        int sq=sqrt(a[u]);
        if(sq*sq==a[u]){
            int s2=0;
            int k=son.size()-1;
            vector<int>cnt2(k+10);
            for(int i=1;i<=k;i++){
                cnt2[i]=son[i]*(s-son[i]);
                s2+=cnt2[i];
            }
            s2/=2;
            int s3=0;
            for(int i=1;i<=k;i++){
                s3+=son[i]*(s2-cnt2[i]);
            }
            s3/=3;
            ans+=s2+s3;
        }
    };dfs2(dfs2,1,-1);
    cout<<ans<<endl;
}