Codeforces Round #782 (Div. 2)题解

A. Red Versus Blue

题意:给出r,b和为n,且r严格大于l。求输出r个R和b个B的字付出,使得最大连续R的个数最小

一共有b个B,那么就有b+1个空位,先平均分配再把额外的R在有些位置加一个

#include<bits/stdc++.h>
using namespace std;
#define AC return 0;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,r,l;
        cin>>n>>r>>l;
        int num=num=r/(l+1);
        
        for(int i=1;i<=l+1;i++){
            for(int j=1;j<=num;j++)cout<<"R";
            if(i<=r%(l+1))cout<<"R";
            if(i==l+1)continue;
            cout<<"B";
        }
        cout<<endl;
    }
    AC
}

B. Bit Flipping

题意:给定一个长度为n的01串,和k次操作,一次操作可以选择一位保留其余位置全部取反

求可得到的最大串

对于01串来说肯定是去贪心考虑,要最大肯定要满足无论付出什么代价都要使前面位为1

然后分k奇偶去讨论就行,其次对于这个操作0次和2次效果是一样的

#include<bits/stdc++.h>
using namespace std;
#define AC return 0;
const int MAXN=2e5+7;
char s[MAXN];
int t,n,k,vis[MAXN];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>k;
        cin>>s;
        int cnt=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n-1;i++){
            if(k&1){
                if(s[i]=='1'){
                    if(cnt<k){vis[i]=1;
                        cnt++;}
                    else s[i]='0';
                }
                else s[i]='1';//对于k为奇数如果不对该位做操作那么一定取反
            }
            else{
                if(s[i]=='0'&&cnt<k){
                    vis[i]=1;
                    cnt++;
                    s[i]='1';
                }
            }
        }
        if(cnt%2){
            if(s[n-1]=='1')s[n-1]='0';
            else s[n-1]='1';
        }
        cout<<s<<endl;
        for(int i=0;i<n-1;i++){
            if(vis[i])cout<<"1 ";
            else cout<<"0 ";
        }
        cout<<k-cnt<<endl;
    }
    AC
}

C. Line Empire

题意:你需要依次占领n个王国,初始点在0,给出a,b。占领一个王国消耗b*他们之间的距离,在占领后可以选择搬迁过去,问最小消耗总和。

对于一个点如果搬迁过去的消耗加占领后面的点的消耗小于原来的,那我们一定要搬迁过去。

我们贪心的去考虑,如果有两个点c1,c2都能搬,那我们一定是先搬到c1,再到c2一定是最优解。相比于直接搬到c2,他们的搬迁费用是一样的,但在c1,c2之间的这些点的占领费用从c1出发会更小。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+7;
#define AC return 0;
#define int long long
int t,n,a,b,c[MAXN],sum;
int check(int i,int st){
    int val1=a*(c[i]-st)+b*(sum-(n-i)*c[i]);//搬过去的费用
    int val2=b*(sum-(n-i)*st);//不搬的费用
    return val1<=val2;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while(t--){
        cin>>n>>a>>b;
        sum=0;
        for(int i=1;i<=n;i++){
            cin>>c[i];
            sum+=c[i];
        }
        int st=0,ans=0;
        for(int i=1;i<=n;i++){
            ans+=b*(c[i]-st);
            sum-=c[i];
            if(check(i,st)){
                ans+=a*(c[i]-st);//搬过去更优
                st=c[i];
            }
        }
        cout<<ans<<endl;
    }
    AC
}

D. Reverse Sort Sum

题意:有一个长度为n的0,1数组,定义bi为a前i个数从小打大排序剩下不变,令数组c为b1-bn的各位置总和,现给出c求出a

对于每个ci,他的组成是由i-1个该位本来的数和若干个1和0,而假设在排序到某x位置之后该位变为0,那么bx后面的情况该位一定位0。假设我们已经知道了该位的数字bit,那么-(i-1)*bit

后就是有多少个1,由于排序范围的扩大该位一定是从1变为0的,那么我们就可以知道在哪个位置变为0,那么该位置对应原来的值为0.

#include<bits/stdc++.h>
using namespace std;
#define AC return 0;
const int MAXN=2e5+7;
int t,n,a[MAXN],ans[MAXN],vis[MAXN];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>t;
    while(t--){
        cin>>n;
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)cin>>a[i];
        int st=1;
        while(a[st]==0){
            ans[st]=1;//标记为1,实际代表0
            st++;//找到第一个不为0的点,前面的点全部是0不影响后面
        }
        
        for(int i=st;i<=n;i++){
            a[i]-=(i-1)*(1-ans[i]);
            ans[a[i]+i]=1;//标记第i个0
            //cout<<a[i]+i<<endl;
        }
        for(int i=1;i<=n;i++){
            if(ans[i]==1)cout<<"0 ";
            else cout<<"1 ";
        }
        cout<<endl;
    }
    AC
}

对于第i位,我们都能找出第i个0所在的位置,剩下的未被标记的点就是1啦。然后0没有那么多的话剩下的点会跳到n以外不需要去考虑。

为了便于理解模拟一组样例吧,对于 2,4,2,4来说显然第一位为1,减去(i-1)后还是2,那么就有2个bi(该位已被排序的bi)在该位是1,那么一定是b1,b2,由此可以确定b3在该位置为0。那么第二位未被标记一定是1,这样对于每一位来说它最少确定后面一位的情况所以可以一直递推下去,第二位4在减去(i-1)后为3,那么第五位为0,超出范围了无需考虑也证明了在该位后无0存在。

EF有缘再补吧!

abc还是写的太慢了orz

等到1点半交的d一发过了,果然赛后正确率直线提升,就是血压有点高了

### 关于Codeforces Round 704 Div. 2 的信息 对于Codeforces Round 704 Div. 2的比赛,虽然未直接提及具体题目解析或参赛体验的内容,但是可以根据平台的一贯风格推测该轮比赛同样包含了多种算法挑战。通常这类赛事会涉及数据结构、动态规划、图论等方面的知识。 考虑到提供的参考资料并未覆盖到此特定编号的比赛详情[^1],建议访问Codeforces官方网站查询官方题解或是浏览社区论坛获取其他选手分享的经验总结。一般而言,在赛后不久就会有详细的解答发布出来供学习交流之用。 为了帮助理解同类型的竞赛内容,这里提供了一个基于过往相似赛事的例子——如何通过居中子数组特性来解决问题的方法: ```cpp // 假设有一个函数用于处理给定条件下的数组恢复问题 vector<int> restoreArray(vector<vector<int>>& adjacentPairs) { unordered_map<int, vector<int>> adj; for (auto& p : adjacentPairs){ adj[p[0]].push_back(p[1]); adj[p[1]].push_back(p[0]); } int start = 0; for(auto& [num, neighbors] : adj){ if(neighbors.size() == 1){ start = num; break; } } vector<int> res(adjacentPairs.size() + 1); unordered_set<int> seen; function<void(int,int)> dfs = [&](int node, int idx){ seen.insert(node); res[idx] = node; for(auto next : adj[node]){ if(!seen.count(next)){ dfs(next, idx + 1); } } }; dfs(start, 0); return res; } ``` 上述代码展示了利用深度优先搜索(DFS)重建原始序列的一种方式,这与某些情况下解决Codeforces比赛中遇到的问题思路相吻合[^4]。 #### 注意事项 由于缺乏针对Codeforces Round 704 Div. 2的具体材料支持,以上解释更多依赖于对同类活动的理解以及编程技巧的应用实例来进行说明。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值