Codeforces Round #763 (Div. 2)

Posted on 2022-01-22 16:29  Capterlliar  阅读(42)  评论(0编辑  收藏  举报

C. Balanced Stone Heaps

题意:给n堆石头,对于第 [3,n] 堆石头,每次选择一个任意的数d,给第 i-1 堆石头加d/3个,i-2 堆石头加d/3*2个,求最后所有石头堆最小数目的最大值。

解:二分嘛。一开始想的直接倒着来一遍,发现没过样例。一想每堆石头只能由后面两堆补足,不能继承再后面的石头。因此把继承的和本来有的分开算,还是倒着来。如果能够继承到足够多的石头,就全部分给前面;如果加上继承的才够,那就把多的那部分分出去;如果加上都不够,那直接return 0 吧。

T了好几次。慎用memset啊慎用memset。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
int a[maxx],t[maxx];
int check(int x){
    for(int i=1;i<=n;i++)
        t[i]=0;
    for(int i=n;i>=3;i--){
        if(a[i]+t[i]>=x){
            if(t[i]>=x){
                t[i-1]+=a[i]/3;
                t[i-2]+=a[i]/3*2;
            }else{
                int temp=a[i]+t[i]-x;
                t[i-1]+=temp/3;
                t[i-2]+=temp/3*2;
            }
        } else
            return 0;
    }
    if(a[1]+t[1]<x||a[2]+t[2]<x)
        return 0;
    return 1;
}
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        int maxn=0;
        for(int i=1;i<=n;i++) {
            scanf("%d", &a[i]);
            maxn=max(maxn,a[i]);
        }
        int l=0,r=maxn,mid;
        int ans;
        while(l<=r){
            mid=l+(r-l)/2;
            if(check(mid)){
                ans=mid;
                l=mid+1;
            }
            else
                r=mid-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

d题算期望,实不相瞒我到现在都不会算期望qaq

**E. Middle Duplication

题意:给出一棵树,每个结点上有个字母,以中序遍历这棵树会得到一个字符串。现在可以重复其中不多于k个字母,但重复的字母的父亲节点也要重复,都算在k里面。问能构成的字典序最小的字符串是什么。

解:树上的问题先拍平了看。有一个字符串,选k个重复,要求字典序最小。那必然从前往后,找到满足类似 s[i]<s[i+1] 的字母重复。如果有一串相等,那就找出第一个与之不相等的比较。

现在把它放回树上。左子树在当前结点前面,右子树在当前节点后面。先不考虑k的限制,如果左孩子比现在小,那我一定选它;如果右孩子比现在大,那我会选当前结点。显然越靠左越好。现在加回k。如果我选了深度为x的结点,那这一路上我还要选它所有的祖先,共x个点。x≤k 即可。

还有卡了半天的是左子树能选就选,右子树中会有点局部满足要求,但选了会导致较大祖先结点重复,最终字典序变大。因此右子树只在当前节点选择后才考虑。其实最后就是几行代码顺序的区别XD

写的时候参考了别人的代码,用树剖记录top的方式计算这条链上共有几个点。很好看。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n,k;
char s[maxx];
int tr[maxx][2],depth[maxx];
int vis[maxx]={0},rvis[maxx]={0};
vector<int> a;
void dfs1(int now,int d){
    depth[now]=d+1;
    if(tr[now][0])
        dfs1(tr[now][0],d+1);
    a.push_back(now);
    if(tr[now][1])
        dfs1(tr[now][1],d+1);
}
int dfs2(int now,int top){
    int flag=0;
    if(tr[now][0])
        flag=dfs2(tr[now][0],top);
    if(flag)
        rvis[now]=1;
    if(!flag&&vis[now]){
        int temp=depth[now]-depth[top]+1;
        if(k>=temp){
            rvis[now]=1;
            k-=temp;
            flag=1;
        } else
            flag=0;
    }
    if(tr[now][1]&&flag)
        dfs2(tr[now][1],tr[now][1]);
    return flag;
}
signed main() {
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&tr[i][0],&tr[i][1]);
    dfs1(1,1);
    int idx=n-1;
    for(int i=n-1;i>=0;i--){
        if(s[a[i]]<s[a[idx]])
            vis[a[i]]=1;
        if(i!=0)
            if(s[a[i]]!=s[a[i-1]])
                idx=i;
    }
    dfs2(1,1);
    for(int i=0;i<a.size();i++){
        printf("%c",s[a[i]]);
        if(rvis[a[i]])
            printf("%c",s[a[i]]);
    }
    printf("\n");
    return 0;
}
View Code