Codeforces Round 784 (Div. 4)

本场小结:
1.对于一些奇怪的题目我们一定要去找存在哪些性质,构造题目和模拟题目同样也是发现性质之后尝试使用暴力枚举
2.双指针的时候注意取结果的位置有时候用while比for更好
3.对于位运算符的出现我们一定要考虑是否具有拆位的性质,区间的也要考虑是否可以使用RMQ的性质

目录

A. Division?

B. Triple

C. Odd/Even Increments

D. Colorful Stamp

E. 2-Letter Strings

F. Eating Candies

G. Fall Down

H. Maximal AND


A. Division?

题目意思:判断每个数所在的区间即可,输出对应语句

直接模拟即可

void solve()
{
    cin>>n;
    if(n<1400) cout<<"Division 4"<


B. Triple


题目意思:给定一个包含 n 元素的数组 a,输出至少出现三次的任何值,如果没有这样的值,则输出 -1。

考虑数据范围直接用map存储即可

void solve()
{
    mp.clear();
    cin>>n;
    int ans=0;
    while(n--){
        int x; cin>>x;
        mp[x]++;
        if(mp[x]>=3) ans=x;
    }
    if(!ans) ans=-1;
    cout<


C. Odd/Even Increments


题目意思:对于一个序列一次操作可以对于所有的奇数索引+1 或者所有偶数索引+1,问是否可以是的最后所有数奇偶性相同

直接判断对于奇数或者偶数的索引个是否都是属于同一种奇偶性即可

void solve()
{
    cin>>n;
    int cnt1=0,cnt2=0,ans1=0,ans2=0;
    for(int i=1;i<=n;i++){
        int x; cin>>x;
        if(i&1){
            if(x%2) cnt1++;
            else cnt2++;
        }
        else{
            if(x%2) ans1++;
            else ans2++;
        }
    }
    if(ans1*ans2+cnt1*cnt2==0) cout<<"YES"<


D. Colorful Stamp


题目意思:有n 个点,最初都为白色。每次染色可将相邻的两个点染成红色与蓝色,或染成蓝色与红色。每次染色会将之前的颜色覆盖掉,问给出的颜色组合是否能通过用这种染色方式染色出来。

我们会发现无论怎么染色两个白色中间都不可能全是一种颜色,用双指针来处理即可,对于一个我们直接特判,可以设置边界哨兵便于处理

char s[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];
    s[0]=s[n+1]='W';
    if(n==1){
        if(s[1]=='W') cout<<"YES"<



E. 2-Letter Strings

题目意思:给定你n个字符长度为2的字符串,求一对中只有一个不一样的数量

我们可以考虑直接使用枚举当前这个位置的一个位置同时另一个位置不同即可

void solve()
{
    cin>>n;
    vector> cnt(12,vector(12,0));
    LL ans=0;
    for(int i=1;i<=n;i++){
        string s; cin>>s;
        for(int j=0;j<2;j++){
            for(char  k='a';k<='k';k++){
                if(k==s[j]) continue;
                string a=s; a[j]=k;
                ans+=cnt[a[0]-'a'][a[1]-'a'];    
            }
        }
        cnt[s[0]-'a'][s[1]-'a']++;
    }
    cout<


F. Eating Candies

题目意思:两个人从序列两边开始移动求想等时两个人可以总共移动的最多的数目

明显的左右两边同时移动考虑双指针有时候使用while会好写一点

LL t,n,m;
LL a[N],b[N],c[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    LL ans1=a[1],ans2=a[n],ans=0;
    int l=1,r=n;
    while(l


G. Fall Down

模拟题寻找性质

题目意思:n x m 的网格是障碍物和羽毛球和空气,障碍物是固定不会动的羽毛球会在空气中下落下求最后状态

对于模拟题就要去找性质,首先数据范围不是很大我们可以考虑稍微暴力的写法,我们发现肯定是要从上而下的来枚举下降的方式然后判断是不是可以下降的即可

char g[M][M];
void solve()
{
    cin>>n>>m;
    memset(g,0,sizeof g);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
        cin>>g[i][j];
    }
    
    for(int j=1;j<=m;j++){
        for(int i=n-1;i>=1;i--){
            if(g[i][j]=='*'){
                if(g[i+1][j]=='o'||g[i+1][j]=='*') continue;
                int q=i;
                while(g[q+1][j]=='.'){
                    swap(g[q+1][j],g[q][j]);
                    q++;
                }
            }
        }
    }
     for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
        cout<



H. Maximal AND


按位与操作中常用拆位
我们考虑从最大的数位开始枚举如果这个位置可以没有0的填上0之后大家都是1那一定
是优的否则就不填这一位
应该熟记^可以使用前缀和,|可以使用RMQ,&使用拆位

 

int sum[35];
int a[N];
void solve()
{
    cin>>n>>m;
    memset(sum,0,sizeof sum);
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++){
        for(int j=0;j<=30;j++){
            if(a[i]>>j&1) ;
            else sum[j]++;
        }
    }
    int ans=0;
    for(int i=30;i>=0;i--){
        if(m>=sum[i]){
            ans|=(1<

你可能感兴趣的:(div4,算法,c++,开发语言)