CF1882 div.2 做题记录

A

题面

扫一遍,令 \(b_i\rightarrow b_{i-1}+1\),若 \(b_i=a_i\)\(b_i\rightarrow b_i+1\)

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
int n;
void solve(){
    read(n);
    int ans=0;
    for(int i=1;i<=n;i++){
        ans++;
        int x;
        read(x);
        if(ans==x){
            ans++;
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t;
    read(t);
    while(t--){
        solve();
    }
    return 0;
}

B

题面

因为集合不能为并集,钦定至少存在 \(x\) 不能被包含,求不包含 \(x\) 的集合的并集的大小,对于所有枚举的 \(x\) 求并集大小的最大值。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=100;
int n,s[N][N],cnt[N],vis[100],ans[100];
void solve(){
    read(n);
    for(int i=1;i<=50;i++){
        vis[i]=0;
    }
    for(int i=1;i<=n;i++){
        read(cnt[i]);
        for(int j=1;j<=cnt[i];j++){
            read(s[i][j]);
            vis[s[i][j]]=1;
        }
    }
    int mx=0;
    for(int i=1;i<=50;i++){
        if(!vis[i]){
            continue;
        }
        for(int j=1;j<=50;j++){
            ans[j]=0;
        }
        for(int j=1;j<=n;j++){
            bool flag=1;
            for(int k=1;k<=cnt[j];k++){
                if(s[j][k]==i){
                    flag=0;
                    break;
                }
            }
            if(flag){
                for(int k=1;k<=cnt[j];k++){
                    ans[s[j][k]]=1;
                }
            }
        }
        int sum=0;
        for(int j=1;j<=50;j++){
            if(ans[j]){
                sum++;
            }
        }
        mx=max(mx,sum);
    }
    write_endl(mx);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t;
    read(t);
    while(t--){
        solve();
    }
    return 0;
}

C

题面

证明一个结论,如果删掉一个数,那么它后面的所有数都是可以选择加入到贡献的。假定删掉的数的位置为 \(x_1,x_2,x_3\dots x_m\)。考虑以奇数位置为分界点,将 \(x_{2\sim m}\) 分为若干段,从后往前处理每个段,将奇数位置的数加入贡献后,所有偶数位置的数都会变成奇数位置的数,从后往前加入贡献就可以保证每个数再删去时都在奇数位置上。只有最前面一段可能还有一段偶数位置的数,删去 \(a_{x_1}\) 即可。

从后往前枚举 \(x_1\),并统计 \((x_1,n]\) 区间内的正数的和 \(sum\),求删去 \(a_{x_1}\) 的贡献与 \(sum\) 的和的最大值。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2e5+10;
int n,s[N],a[N];
void solve(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
        if(a[i]>0){
            s[i]=a[i];
        }
        else{
            s[i]=0;
        }
    }
    s[n+1]=0;
    int ans=0;
    for(int i=n;i>=1;i--){
        s[i]=s[i+1]+s[i];
        if(i&1){
            ans=max(ans,a[i]+s[i+1]);
        }
        else{
            ans=max(ans,s[i+1]);
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t;
    read(t);
    while(t--){
        solve();
    }
    return 0;
}

D

题面

先考虑以 \(1\) 为根的情况,模拟一条链 \(1\rightarrow 2\rightarrow 3\rightarrow 4\)

\(1\) 的修改是没有意义的,因为是所有点都被修改,等价于没变,所以直接令最后的异或值为 \(a_1\) 即可;
\(2\) 的修改值为 \(a_1\oplus a_2\)
\(3\) 的修改值为 \(a_1\oplus a_2\oplus a_3\oplus a_1=a_2\oplus a_3\)
\(4\) 的修改值为 \(a_1\oplus a_2\oplus a_2\oplus a_3\oplus a_4\oplus a_1=a_3\oplus a_4\)

可以发现每个点的修改值都为 \(a_u\oplus a_{fa}\),其中 \(fa\) 表示 \(u\) 在当前树下的父亲,若 \(u\) 为树的根,则不修改。这个修改值和 \(siz\) 都是换根好维护的,直接求出以 \(1\) 为根的树的答案,再换根求其它的答案。复杂度 \(O(n)\)

E1

题面

赛时脑抽了,没想出来怎么还原,只知道怎么调整。

将两个序列分开,可以先还原每个序列再调整操作次数的差别。

先讲调整吧,将选择序列第一个数看作将序列顺着循环位移一次,选择最后一个数看作将序列逆着循环位移一次。如果序列长度为奇数,可以通过选择序列长度次 \(1\),改变答案操作次数的奇偶性,将此操作看作调整 \(1\)。而先选第一个,再选最后一个,可以增加两次操作次数,将此操作看作调整 \(2\)

还原可以每次将 \(1\sim x\) 移到 \(x+1\) 前。这个操作的话,假定 \(1\sim x\) 已经是一段连续的序列,先找到 \(x\) 的位置,选择其后面的一个数,因为选择的是后面的数,不会改变前面的数的相对顺序,所以 \(1\sim x\) 就到了序列的末尾。再找到 \(x+1\) 的位置,选择该位置 \(1\sim x\)\(x+1\) 就已经连续了。

令还原两个序列的操作次数分别为 \(a,b\)。若 \(b-a\) 为偶数,只需要进行若干次调整 \(2\) 即可;若 \(b-a\) 为奇数,显然要进行一次调整 \(1\),再进行若干次调整 \(2\)。如果两个序列长度均为偶数,显然无解。其它的按照上述方法调整即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=3000;
int n,m,a[N],b[N],tmp[N];
vector<int>ansa,ansb;
void worka(){
    for(int i=1;i<n;i++){
        int pos=0;
        for(int j=1;j<=n;j++){
            if(a[j]==i){
                pos=j;
                break;
            }
        }
        if(a[pos+1]==i+1){
            continue;
        }
        if(pos+1>n){
            for(int j=1;j<=n;j++){
                if(a[j]==i+1){
                    pos=j;
                    break;
                }
            }
            ansa.pb(pos);
            for(int i=1;i<=n;i++){
                tmp[i]=a[i];
            }
            int cnt=0;
            for(int i=pos+1;i<=n;i++){
                a[++cnt]=tmp[i];
            }
            a[++cnt]=tmp[pos];
            for(int i=1;i<pos;i++){
                a[++cnt]=tmp[i];
            }
            continue;
        }
        ansa.pb(pos+1);
        int cnt=0,Pos=0;
        for(int j=pos+2;j<=n;j++){
            tmp[++cnt]=a[j];
            if(a[j]==i+1){
                Pos=cnt;
            }
        }
        tmp[++cnt]=a[pos+1];
        for(int j=1;j<=pos;j++){
            tmp[++cnt]=a[j];
            if(a[j]==i+1){
                Pos=cnt;
            }
        }
        cnt=0;
        ansa.pb(Pos);
        for(int j=Pos+1;j<=n;j++){
            a[++cnt]=tmp[j];
        }
        a[++cnt]=tmp[Pos];
        for(int j=1;j<Pos;j++){
            a[++cnt]=tmp[j];
        }
    }
}
void workb(){
    for(int i=1;i<m;i++){
        int pos=0;
        for(int j=1;j<=m;j++){
            if(b[j]==i){
                pos=j;
                break;
            }
        }
        if(b[pos+1]==i+1){
            continue;
        }
        // cerr<<i<<' '<<pos<<' '<<b[pos]<<' '<<b[pos+1]<<endl;
        if(pos+1>m){
            for(int j=1;j<=m;j++){
                if(b[j]==i+1){
                    pos=j;
                    break;
                }
            }
            ansb.pb(pos);
            for(int i=1;i<=m;i++){
                tmp[i]=b[i];
            }
            int cnt=0;
            for(int i=pos+1;i<=m;i++){
                b[++cnt]=tmp[i];
            }
            b[++cnt]=tmp[pos];
            for(int i=1;i<pos;i++){
                b[++cnt]=tmp[i];
            }
            continue;
        }
        ansb.pb(pos+1);
        int cnt=0,Pos=0;
        for(int j=pos+2;j<=m;j++){
            tmp[++cnt]=b[j];
            if(b[j]==i+1){
                Pos=cnt;
            }
            // cerr<<b[j]<<' ';
        }
        tmp[++cnt]=b[pos+1];
        for(int j=1;j<=pos;j++){
            tmp[++cnt]=b[j];
            if(b[j]==i+1){
                Pos=cnt;
            }
        }
        // for(int i=1;i<=m;i++){
        //     cerr<<tmp[i]<<' ';
        // }
        // cerr<<endl;
        cnt=0;
        ansb.pb(Pos);
        for(int j=Pos+1;j<=m;j++){
            b[++cnt]=tmp[j];
        }
        b[++cnt]=tmp[Pos];
        for(int j=1;j<Pos;j++){
            b[++cnt]=tmp[j];
        }
    }
}
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    for(int i=1;i<=m;i++){
        read(b[i]);
    }
    worka();
    workb();
    int siza=ansa.size(),sizb=ansb.size(),delta=siza-sizb;
    // for(auto x:ansa){
    //     cerr<<x<<' ';
    // }
    // cerr<<endl;
    // for(auto x:ansb){
    //     cerr<<x<<' ';
    // }
    if(delta%2==0){
        if(delta>0){
            while(delta>0){
                delta-=2;
                ansb.pb(1);
                ansb.pb(m);
            }
        }
        else{
            while(delta<0){
                delta+=2;
                ansa.pb(1);
                ansa.pb(n);
            }
        }
    }
    else{
        if(n%2==0&&m%2==0){
            write_endl(-1);
            return;
        }
        if(n&1){
            for(int i=1;i<=n;i++){
                ansa.pb(1);
            }
            delta+=n;
        }
        else{
            for(int i=1;i<=m;i++){
                ansb.pb(1);
            }
            delta-=m;
        }
        if(delta>0){
            while(delta>0){
                delta-=2;
                ansb.pb(1);
                ansb.pb(m);
            }
        }
        else{
            while(delta<0){
                delta+=2;
                ansa.pb(1);
                ansa.pb(n);
            }
        }
    }
    write_endl(ansa.size());
    for(int i=0;i<ansa.size();i++){
        write_space(ansa[i]),write_endl(ansb[i]);
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

E2

题面

先咕着,主要还不会

posted @ 2023-09-26 15:28  luo_shen  阅读(11)  评论(0编辑  收藏  举报