Educational Codeforces Round 65 (Rated for Div. 2) A-F解题报告

在这里插入图片描述
这场被B题坑了一小时,其他做起来都是一眼题。

A:正常模拟就好
代码:

#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;


int main(){
    IO;
    int t;cin>>t;
    while(t--){
        int n;string s;
        cin>>n>>s;
        if(n<11){
            cout<<"NO"<<'
';
            continue;
        }
        int x = n-11,flag = -1;
        forn(i,n){
            if(s[i]=='8'){
                flag = i;
                break;
            }
        }
        if(flag==-1){
            cout<<"NO"<<'
';
            continue;
        }
        if(flag>x){
            cout<<"NO"<<'
';
            continue;
        }
        cout<<"YES"<<'
';
    }


    return 0;
}

B题:
这题放两个思路

  1. 思路一:询问12 23确定1 2 3的值;询问45 56确定4 5 6的值
  2. 思路二:取六个数的全排列符合输出
    代码一:
#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

vector<int>ans,cnt;
int z[] = {32,60,64,92,168,120,128,184,336,240,345,630,368,672,966};
int x[] = {4,4,4,4,4,8,8,8,8,15,15,15,16,16,23};
int y[] = {8,15,16,23,42,15,16,23,42,16,23,42,23,42,42};
void get(int t){
    forn(i,15){
        if(t==z[i]){
            cnt.push_back(x[i]);
            cnt.push_back(y[i]);
        }
    }
}

int vis[100];

int main(){
    int num[6]={4, 8, 15, 16, 23, 42};
    int a;
    printf("? 1 2
");
    //cout<<"? 1 2"<<'
';
    fflush(stdout);
    cin>>a;
    get(a);
    printf("? 2 3
");
    //cout<<"? 2 3"<<'
';
    fflush(stdout);
    cin>>a;
    get(a);

    forn(i,4){
        vis[cnt[i]]++;
    }
    forn(i,4){
        if(vis[cnt[i]]==1){
            ans.push_back(cnt[i]);
            break;
        }
    }
    forn(i,4){
        if(vis[cnt[i]]==2){
            ans.push_back(cnt[i]);
            break;
        }
    }
    for(int i=3;i>=0;i--){
        if(vis[cnt[i]]==1){
            ans.push_back(cnt[i]);
            break;
        }
    }
    cnt.clear();
    printf("? 4 5
");
    //cout<<"? 4 5"<<'
';
    fflush(stdout);
    cin>>a;
    get(a);
    printf("? 5 6
");
    //cout<<"? 5 6"<<'
';
    fflush(stdout);
    cin>>a;
    get(a);
    cerr<<a<<'
';
    forn(i,4){
        vis[cnt[i]]++;
    }
    forn(i,4){
        if(vis[cnt[i]]==1){
            ans.push_back(cnt[i]);
            break;
        }
    }
    forn(i,4){
        if(vis[cnt[i]]==2){
            ans.push_back(cnt[i]);
            break;
        }
    }
    for(int i=3;i>=0;i--){
        if(vis[cnt[i]]==1){
            ans.push_back(cnt[i]);
            break;
        }
    }


    printf("! ");
    forn(i,6){
        printf("%d ",ans[i]);
    }
    printf("
");

    return 0;
}

代码二:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

int main(){
    vector<int>v = {4, 8, 15, 16, 23, 42},a;
    cout<<"? 1 2"<<'
';
    int x;cin>>x;a.push_back(x);
    cout<<"? 2 3"<<'
';
    cin>>x;a.push_back(x);
    cout<<"? 3 4"<<'
';
    cin>>x;a.push_back(x);
    cout<<"? 4 5"<<'
';
    cin>>x;a.push_back(x);
    do{
        if(v[0]*v[1]!=a[0]) continue;
        if(v[1]*v[2]!=a[1]) continue;
        if(v[2]*v[3]!=a[2]) continue;
        if(v[3]*v[4]!=a[3]) continue;
        cout<<'!';
        for(auto x:v) cout<<' '<<x;
        return cout<<'
',0;
    }while(next_permutation(v.begin(),v.end())); 
}

C题:裸的并查集 比赛时找不到板子我手敲都5分钟写完

#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn  = 5e5+5;

int par[maxn],rankk[maxn],a[maxn];

void init(int n){
    for1(i,n){
        rankk[i] = 1;
        par[i] = i;
    }
}

int find(int x){
    return par[x]==x?x:par[x] = find(par[x]);
}

void unit(int x,int y){
    x = find(x),y = find(y);
    if(x==y) return;
    if(rankk[x]>rankk[y]) swap(x,y);
    par[x] = y;
    rankk[y] += rankk[x];
}

int main(){
    IO;
    int n,m;cin>>n>>m;
    init(n);    
    forn(i,m){
        int x;cin>>x;
        forn(i,x) cin>>a[i];
        for1(i,x-1) unit(a[i],a[i-1]);
    }
    for1(i,n) cout<<rankk[find(i)]<<' ';
    cout<<'
';

    return 0;
}

D题不难想出 左括号按01 右括号按01顺下去
代码:

#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;

int ans[maxn];

int main(){
    IO;
    int n;string s;cin>>n>>s;
    int a =0,b=0;
    forn(i,n){
        if(s[i]=='('){
            a++;
            if(a&1) ans[i] = 0;
            else ans[i] = 1;
        }
        else{
            b++;
            if(b&1) ans[i] = 0;
            else ans[i] = 1;
        }
    }
    forn(i,n) cout<<ans[i];
    cout<<'
';
    return 0;
}

E题 双指针
n个数 删除[1,J]满足数组不递减 肯定满足删除[1,j+1] [1,j+2]…[1,n]都满足不递减
那我们先以左端点为1,找到最小的右端点的值j,此时ans+=k-j+1
然后我们来看看[2,j]可以吗 不可以就看看[2,j+1] [2,j+2]…知道找到一个新的最小j,此时ans+=k-j+1
以此类推我们滑动双指针的复杂度为O(4*N)

因为n为1e6 每次判断必须是O1或者Ologn,这边就是这个思路的难点了
这里我是O1的,存了4个数组

  1. l数组记录大小为i的数第一次出现的位置
  2. r数组记录大小为i的数最后一次出现的位置
  3. L数组记录区间(i~n)大小的数第一次出现的位置
  4. R数组记录区间(1-i)大小的数最后一次出现的位置
    这些预处理也都是On的处理

判断以1为左端点时,我只要判断L[j]是否小于r[j-1]
定左端点时:
我要确保左端点前的L[i-1](左端点前所有的数最后一次出现的位置)
小于R[j+1](右端点后的所有的数第一次出现的位置)

再剩下的就是细节调整了
因为我R初始化了正无穷,所以j最大为k
当j=k时 ans+=k-j+1,如果此时不符合条件就不能继续算下去了

然后我们发现如果左端点前的R[i-2](左端点变化前的所有的数最后一次出现的位置)
大于l[i-1](更新的这个值)那么此时操作已经无效可以终止了break。

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 1e6+5;
const int inf = 0x3f3f3f3f;

int a[maxn],l[maxn],r[maxn],L[maxn],R[maxn];

int main(){
    IO;
    int n,k;cin>>n>>k;
    memset(l,inf,sizeof(l));
    memset(L,inf,sizeof(L));
    memset(r,-1,sizeof(r));
    memset(R,-1,sizeof(R));
    for1(i,n){
        cin>>a[i];
        l[a[i]] = min(i,l[a[i]]);
        r[a[i]] = i; 
    }
    for1(i,k) R[i] = max(r[i],R[i-1]);
    for(int i=k;i>=1;i--) L[i] = min(l[i],L[i+1]);
    int j = k;
    while(j>1&&L[j+1]>=r[j]) j--;
    ll ans = 0;
    ans+=k-j+1;
    for(int i=2;i<=k;i++){
        if(R[i-2]>l[i-1]) break;
        while(j<i||R[i-1]>L[j+1]) j++;
        ans+=k-j+1;
    }
    cout<<ans<<'
';
    return 0;
}

F题留坑

人一我百,人十我万。
原文地址:https://www.cnblogs.com/AlexPanda/p/12520332.html