Educational Codeforces Round 102 (Rated for Div. 2)

Educational Codeforces Round 102 (Rated for Div. 2)

A. Replacing Elements

做法:

水题,直接判断数组是否都小于\(d\),如果都小于\(d\),那么\(YES\),否则判断最小的和次小的相加小于\(d\),如果小于那么\(YES\),否则\(NO\)

代码:

不贴了^^_

B. String LCM

做法:

要满足\(LCM(s,t)\)要找s和t的最小循环节\(st\),找到后循环循环节\((s/st)\times(t/st)\)次后,就是\(LCM(s,t)\),如果找不到\(st\),就为\(-1\)

代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=3e5+7;
int t;
string s,d;
int main(){
    cin>>t;
    while(t--){
        cin>>s;
        cin>>d;
        if(s.size()<d.size()){
            swap(s,d);
        }
        int ok=0;
        string a="",ans;
        int ans1=0,ans2=0;
        for(int i=0;i<d.size();i++){
            a+=d[i];
            int flag1=0,flag2=0,cnt1=0,cnt2=0;
            string ha="";
            for(int j=1;j<=20;j++){
                ha+=a;
                if(ha==s){
                    flag1=1;
                    cnt1=j;
                    break;
                }
            }
            ha="";
            for(int j=1;j<=20;j++){
                ha+=a;
                if(ha==d){
                    flag2=1;
                    cnt2=j;
                    break;
                }
            }
            if(flag1==1&&flag2==1){
                ans=a;
                ans1=cnt1;
                ans2=cnt2;
                ok=1;
            }
        }
        if(ok==1){
            for(int i=1;i<=ans1*ans2;i++){
                cout<<ans;
            }
            cout<<endl;
        }else{
            cout<<"-1"<<endl;
        }
    }
}

C. No More Inversions

做法:

观察我们可以发现a和变化后的b都是关于在第k位不完全对称的,a排列的逆序对的产生也是在超过的k位后产生的,也就是说我们构造b的话,构造b的前k位的逆序对与a的后k位的逆序对相等,即有n-k个排列逆序的,最后保证字典序大。

举个例子:\(n=5,k=3\)

\(a=[1,2,3,2,1]\)。考虑a后k个的逆序对要和构造的\(b\)\(k\)个的逆序对相等。那么\(b=[3,2,1,2,3]\)。则\(p=[3,2,1]\)

代码:

#include <iostream>
using namespace std;
int t;
int n,k;
int main(){
    cin>>t;
    while(t--){
        cin>>n>>k;
        int cnt=n-k;
        cnt=k-cnt;
        for(int i=1;i<=cnt-1;i++){
            cout<<i<<" ";
        }
        for(int i=k;i>=cnt;i--){
            cout<<i<<" ";
        }
        cout<<endl;
    }
}

D. Program

做法:

将+抽象位+1,-抽象位-1,数组a记录前缀和,要求数的个数,就是在\(l-r\)\(Max-Min+1\),用线段树RMQ处理区间最大值和最小值问题。

代码:

#include <iostream>
#define lch 2*k
#define rch 2*k+1
#define mid (l+r)/2
using namespace std;
const int N=2e5+7;
int t;
int n,m,a[N],Max,Min,maxn[4*N],minn[4*N];
void init(int k,int l,int r){
    if(l>=r){
        maxn[k]=minn[k]=a[l];
        return;
    }
    init(lch,l,mid);
    init(rch,mid+1,r);
    maxn[k]=max(maxn[lch],maxn[rch]);
    minn[k]=min(minn[lch],minn[rch]);
}
 
void qry(int k,int l,int r,int ql,int qr,int val){
    if(ql>qr){
        return;
    }
    if(ql<=l&&r<=qr){
        Max=max(Max,maxn[k]+val);
        Min=min(Min,minn[k]+val);
        return ;
    }
    if(ql<=mid) qry(lch,l,mid,ql,qr,val);
    if(mid+1<=qr) qry(rch,mid+1,r,ql,qr,val);
    return;
}
int main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            char ch;
            cin>>ch;
            if(ch=='+'){
                a[i]=a[i-1]+1;
            }else{
                a[i]=a[i-1]-1;
            }
        }
        init(1,1,n);
        while(m--){
            int ql,qr;
            cin>>ql>>qr;
            Max=-1e9,Min=1e9;
            qry(1,1,n,1,ql-1,0);
            qry(1,1,n,qr+1,n,-(a[qr]-a[ql-1]));
            Min=min(0,Min);
            Max=max(0,Max);
            cout<<Max-Min+1<<endl;
        }
    }
}
posted @ 2021-01-15 10:59  高级牛头人  阅读(49)  评论(0编辑  收藏  举报