Codeforces Round 923 (Div. 3)(A~D)

A. Make it White

找出第一个B和最后一个B的位置。

#include 
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;

string s;

void solve(){
    cin>>s>>s;
    s="1"+s;

    pairpos;
    per(i,1,s.length())if(s[i]=='B'){
        if(!pos.fr)pos.fr=i;
        pos.se=i;
    }

    if(pos.fr)cout<>t;
    while(t--)solve(),init();
    return 0;
}

B. Following the String

模拟题,如果序列里面是0,那就输出一个没出现过的,不然就从出现过的地方拿一个,此处用的队列。

#include 
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
const int N=2e5+5;

int n,a;
char idx='a';
queueq[N];

void solve(){
    cin>>n;
    per(i,1,n){
        cin>>a;
        if(!a){
            cout<>t;
    while(t--)solve(),init();
    return 0;
}

C. Choose the Different Ones!

在数组A里面选k/2个数,在数组B里面选k/2个数,要求1~k里面每个数都出现一次。

因为数组的值很小,只有1e6,所以可以给A和B数组转换成数值存储,例如cnt[5]++,代表5出现一次,这样方便查数,即cnta[5]就知道数组a中5出现了几次。

因为选的次数有限,所以把A数组仅有的数和B数组仅有的数选出来,再去选都有的数。

#include 
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
const int N=2e5+5,AN=1e6+5;

int n,m,k,cnta[AN],cntb[AN],tmp;
bool vis[AN];

vectora,b;

void no(){
    cout<<"NO"<>n>>m>>k;
    per(i,1,n)cin>>tmp,cnta[tmp]++,a.push_back(tmp);
    per(i,1,m)cin>>tmp,cntb[tmp]++,b.push_back(tmp);

    cntb[0]=cnta[0]=k/2;
    per(i,1,k){
        if(cnta[i] and !cntb[i] or !cnta[i] and cntb[i]){
            if(cnta[i]){
                if(cnta[0]){
                    vis[i]=true;
                    cnta[0]--;
                }else return no();
            }else{
                if(cntb[0]){
                    vis[i]=true;
                    cntb[0]--;
                }else return no();
            }
        }else if(cnta[i]+cntb[i]==0)return no();
    }

    per(i,1,k){
        if(!vis[i]){
            if(cnta[i]){
                cnta[0]--;
            }else if(cntb[i]){
                cntb[0]--;
            }else return no();
        }
    }

    cout<<"YES"<>t;
    while(t--)solve(),init();
    return 0;
}

提交之前先估计一下总体复杂度,不小心可能就TLE了

D. Find the Different Ones!

给你一个数组A,多次询问,每次问一个区间里面是否全部相等,如果不相等,任意输出两个不相等的下标。

数组大小不超过2e5,总的询问大小不超过2e5,那么每次询问复杂度只能是log级别或者以下。

一个区间里面如果有不相等的那么横着扫过去肯定有解。

    per(i,l+1,r){
        if(a[i]!=a[i-1]){
            cout<

但是这是一个n级别的,所以考虑把一样进行压缩,即1 1 1 1 1,变成5 1。

这道题不需要具体的值,只要不同就行,所以每次记录一下开头一样的位置。

比如1 1 1 2 2 3,就压缩成1 4 6,即第一个出现了不一样,第四个出现了不一样。

因为位置是有序的,所以可以使用二分来询问。

#include 
//#define int long long
#define per(i,j,k) for(int (i)=(j);(i)<=(k);++(i))
#define rep(i,j,k) for(int (i)=(j);(i)>=(k);--(i))
#define fr first
#define se second
#define endl '\n'
using namespace std;
const int N=2e5+5;

int n,a[N],q,l,r;

sets;

void nodif(){
    cout<<-1<<" "<<-1<>l>>r;
    auto tmp=s.upper_bound(l);
    if(tmp==s.end())return nodif();
    if(r<*tmp)return nodif();
    else cout<>n;
    per(i,1,n){
        cin>>a[i];
        if(i==1)s.insert(i);
        if(a[i]!=a[i-1])s.insert(i);
    }

    cin>>q;
    while(q--)query();
    cout<>t;
    while(t--)solve(),init();
    return 0;
}

你可能感兴趣的:(Codeforces,codeforce,c++,算法,思维,数据结构,div3)