2025.1.26 Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)

比赛链接

Solved:5/9


A. String

题意:给一个字符串,每次可以选一个相邻字符不同的子串翻转,问最少几次能变成全 0 串。

注意到每次操作至多只能减少一个 1,而每次选一个 1 变成 0 就能做到这一点,所以答案就是 1 的个数。

void solve(){
    string a;
    cin>>a;
    int res=0;
    for(char x:a)res+=x=='1';
    cout<<res<<'\n';
}

B. Clockwork

题意:有 \(n\) 个计时器,第 \(i\) 个计时器初始为 \(a_i\)。每一秒所有计时器时间 -1,然后你可以移动到一个相邻的计时器或者不动并将其时间重置回 \(a_i\)。如果任意时刻某个计时器时间为 0 则失败。问能否保证一直不失败。

显然最优策略就是来回遍历整个序列。如果一个计时器在一周期内会变到 0 就肯定失败。

bool solve(){
    int n;
    cin>>n;
    vector<int> a(n);
    for(int& x:a)cin>>x;
    for(int i=0;i<n;++i){
        if(a[i]<=max(i,n-1-i)*2)return 0;
    }
    return 1;
}

C. Cirno and Operations

题意:给一个序列,每次可以选择反转或取差分,问任意多次操作后序列所有数之和的最大值。

注意到本质不同的操作只有多次差分或反转一次再多次差分。直接 \(O(n^2)\) 暴力即可。

void solve(){
    int n;
    cin>>n;
    vector<ll> a(n),b(n);
    for(ll& x:a)cin>>x;
    ll res=-inf;
    for(int i=0;i<n;++i){
        ll sum=0;
        for(int j=0;j<n-i;++j)sum+=a[j];
        res=max(res,i?abs(sum):sum);
        for(int j=0;j<n-i-1;++j)b[j]=a[j+1]-a[j];
        a=b;
    }
    cout<<res<<'\n';
}

D. Balanced Tree

题意:给一棵树,每个点的点权取值在一个区间中。现可以做多次操作,每次选择一棵子树将其所有点点权加 1。分配初始点权后通过上述操作让所有点权相等,求这个相等的点权的最小值。

任取一个点作为根,令 \(d_u = a_u - a_{fa_u}\),则每次操作相当于令 \(d_u\) 加一或者令 \(d_u\) 减一的同时使答案加 1。我们最终目标是让所有 \(d_u\) 变为 0,故答案是 \(a_1 + \sum_{i=2}^n \max\{0,d_i\}\)

直接贪心选每个点的点权为子节点点权的最大值即可。若在区间外则改为端点值。

const int N=2e5+5;
int n,a[N],b[N],c[N],x,y;
ll ans;
vector<int> e[N];
void adde(int x,int y){
    e[x].push_back(y);
}

void dfs(int u,int f){
    c[u]=a[u];
    for(int v:e[u])if(v^f)dfs(v,u),c[u]=max(c[u],c[v]);
    c[u]=min(c[u],b[u]);
    for(int v:e[u])if(v^f)ans+=max(0,c[v]-c[u]);
}

void solve(){
    cin>>n;
    for(int i=1;i<=n;++i)e[i].clear();
    for(int i=1;i<=n;++i)cin>>a[i]>>b[i];
    for(int i=1;i<n;++i)cin>>x>>y,adde(x,y),adde(y,x);
    ans=0,dfs(1,0);
    cout<<ans+c[1]<<'\n';
}

E1. The Game (Easy Version)

题意:给一棵树,两人轮流操作,每人可以选择点权小于上一个人选择的点权的点删去它及其整棵子树,不能操作者胜。给出一个先手首次选择可以取胜的点。

按点权从大到小枚举,找到第一个取完后手能继续取的点即可。因为后面的点必然全都是必败点。

const int N=3e5+5;
int n,a[N],x,y;
vector<int> e[N],o[N];
void adde(int x,int y){
    e[x].push_back(y);
}

int dfn[N],sz[N],id;
void dfs(int u,int f){
    dfn[u]=++id,sz[u]=1;
    for(int v:e[u])if(v^f)dfs(v,u),sz[u]+=sz[v];
}

struct bit{
    int c[N];
    void clear(){
        memset(c,0,sizeof(int)*(n+1));
    }
    void upd(int x,int y){
        for(;x<=n;x+=x&-x)c[x]+=y;
    }
    int sum(int x){
        int res=0;
        for(;x;x-=x&-x)res+=c[x];
        return res;
    }
    int qry(int x){
        return sum(dfn[x]+sz[x]-1)-sum(dfn[x]-1);
    }
}T;

void solve(){
    cin>>n;
    for(int i=1;i<=n;++i)e[i].clear(),o[i].clear();
    T.clear();
    for(int i=1;i<=n;++i)cin>>a[i],o[a[i]].push_back(i);
    for(int i=1;i<n;++i)cin>>x>>y,adde(x,y),adde(y,x);
    id=0,dfs(1,0);
    int cnt=0;
    bool fl=1;
    for(int i=n;i;--i)if(o[i].size()){
        vector<int> tmp;
        for(int u:o[i]){
            if(T.qry(u)==cnt||fl==1)continue;
            cout<<u<<'\n';
            return;
        }
        for(int u:o[i])T.upd(dfn[u],1);
        cnt+=o[i].size(),fl=0;
    }
    cout<<"0\n";
}
posted @ 2025-01-27 21:44  EssnSlaryt  阅读(68)  评论(0)    收藏  举报