Educational Codeforces Round 169 (Rated for Div. 2) 补题记录(A~F)

打的还行

A

容易发现当且仅当 n=2|a1a2|>1 时才可能,否则一定不可能。

const int N=1000100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        F(i,1,n)cin>>a[i];
        sort(a+1,a+n+1);
        if(n==2){
            if(a[2]-a[1]==1)cout<<"NO\n";
            else cout<<"YES\n";
        }else{
            cout<<"NO\n";
        }
    }
    return 0;
}

B

暴力枚举求出两段区间的公共区间长度,然后如果左边还有一个位置被至少一条线段覆盖那么需要加 1,右边也同理。细节有点多。

const int N=1000100;
int a[N];
int get(int a,int b,int c,int d){
    if(b<c||a>d)return 0;
    int s=min(b,d)-max(a,c)+1;
    return max(0ll,s);
}
signed main(){
    int T;cin>>T;
    while(T--){
        int l,r,L,R;
        cin>>l>>r>>L>>R;
        int cnt=0;
        int p2=min(r,R),p1=max(l,L);
        if(get(l,r,L,R)==0){
            cout<<"1\n";
            continue;
        }
        if(get(l,r,L,R)==1){
            cout<<"2\n";
            continue;
        }
        --r,--R;
        F(i,1,100){
            if(l<=i&&i<=r&&L<=i&&i<=R)++cnt;
        }
        if(l!=L)++cnt;
        if(r!=R)++cnt;
        cout<<cnt<<'\n';
    }
    return 0;
}

C

很显然从大到小排序则若 i0(mod2) 则这个元素归 Bob,否则归 Alice。显然 Bob 只能让自己的元素的值和在它前面一个位置的元素的值尽量的接近的时候最优。因此直接暴力枚举 Bob 的每一个元素计算其可以最多加多少,贪心计算即可。时间复杂度为 O(nlogn),使用基数排序可以做到 O(n)

const int N=1000100;
int a[N];
signed main(){
    int T;cin>>T;
    while(T--){
        int n,k;cin>>n>>k;
        F(i,1,n)cin>>a[i];
        sort(a+1,a+n+1,greater<int>());
        int cnt=0;
        for(int i=2;i<=n;i+=2){
            int diff=a[i-1]-a[i];
            diff=min(diff,k);
            a[i]+=diff;
            k-=diff;
        }
        sort(a+1,a+n+1,greater<int>());
        F(i,1,n){
            if(i&1)cnt+=a[i];
            else cnt-=a[i];
        }
        cout<<cnt<<'\n';
    }
    return 0;
}

D

大分讨。发现若 i 可以直接到达 j 则答案就是 |ij|。否则要么不能到达要么无解,要么在经过恰好一个中转点的情况下就能到达 j。因此设 fi,0/1/2/3/4/5 表示 i 开始往左第一个为 BGBRBYGRGYRY 的位置,gi,0/1/2/3/4/5 表示 i 开始往右第一个为 BGBRBYGRGYRY 的位置。这个可以一遍扫描预处理。对于每一个 Sxi 字符串的值,只需要枚举其可以到达且和自己不完全相同的 8 个不同的最近组合位置即可。时间复杂度为 O(n)

using namespace std;
const int N=500100;
int a[N],fa[N];
string s[N];
int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
int f[N][6],g[N][6];
signed main(){
    int T;cin>>T;
    while(T--){
        int n,q;cin>>n>>q;
        F(i,1,n)cin>>s[i];
        F(i,1,n)if(s[i][0]>s[i][1])swap(s[i][0],s[i][1]);
        F(i,1,n)fa[i]=i;
        F(i,0,n+1)
            F(j,0,5)f[i][j]=g[i][j]=-1;
        int la[6]={1,1,1,1,1,1};
        F(i,1,n){
            if(s[i]=="BG"){
                F(j,la[0],i)g[j][0]=i;
                la[0]=i+1;
            }
            if(s[i]=="BR"){
                F(j,la[1],i)g[j][1]=i;
                la[1]=i+1;
            }
            if(s[i]=="BY"){
                F(j,la[2],i)g[j][2]=i;
                la[2]=i+1;
            }
            if(s[i]=="GR"){
                F(j,la[3],i)g[j][3]=i;
                la[3]=i+1;
            }
            if(s[i]=="GY"){
                F(j,la[4],i)g[j][4]=i;
                la[4]=i+1;
            }
            if(s[i]=="RY"){
                F(j,la[5],i)g[j][5]=i;
                la[5]=i+1;
            }
        }
        F(i,0,5)la[i]=n;
        G(i,n,1){
            if(s[i]=="BG"){
                G(j,la[0],i)f[j][0]=i;
                la[0]=i-1;
            }
            if(s[i]=="BR"){
                G(j,la[1],i)f[j][1]=i;
                la[1]=i-1;
            }
            if(s[i]=="BY"){
                G(j,la[2],i)f[j][2]=i;
                la[2]=i-1;
            }
            if(s[i]=="GR"){
                G(j,la[3],i)f[j][3]=i;
                la[3]=i-1;
            }
            if(s[i]=="GY"){
                G(j,la[4],i)f[j][4]=i;
                la[4]=i-1;
            }
            if(s[i]=="RY"){
                G(j,la[5],i)f[j][5]=i;
                la[5]=i-1;
            }
        }
        while(q--){
            int x,y;cin>>x>>y;
            if(x==y)cout<<"0\n";
            else{
                if(x>y)swap(x,y);
                set<char>se={s[x][0],s[x][1],s[y][0],s[y][1]};
                if(se.size()!=4)cout<<abs(y-x)<<'\n';
                else{
                    int res=1e18;
                    if(s[x]=="BG"){
                        {int p1=f[x][1],p2=g[x][1];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][2],p2=g[x][2];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][3],p2=g[x][3];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][4],p2=g[x][4];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(s[x]=="BR"){
                        {int p1=f[x][0],p2=g[x][0];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][2],p2=g[x][2];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][3],p2=g[x][3];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][5],p2=g[x][5];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(s[x]=="BY"){
                        {int p1=f[x][0],p2=g[x][0];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][1],p2=g[x][1];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][4],p2=g[x][4];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][5],p2=g[x][5];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(s[x]=="GR"){
                        {int p1=f[x][0],p2=g[x][0];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][1],p2=g[x][1];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][4],p2=g[x][4];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][5],p2=g[x][5];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(s[x]=="GY"){
                        {int p1=f[x][0],p2=g[x][0];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][2],p2=g[x][2];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][3],p2=g[x][3];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][5],p2=g[x][5];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(s[x]=="RY"){
                        {int p1=f[x][1],p2=g[x][1];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][2],p2=g[x][2];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][3],p2=g[x][3];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                        {int p1=f[x][4],p2=g[x][4];
                        if(~p1)res=min(res,abs(x-p1)+abs(p1-y));
                        if(~p2)res=min(res,abs(x-p2)+abs(p2-y));}
                    }
                    if(res>=1e17)res=-1;
                    cout<<res<<'\n';
                }
            }
        }
    }
    return 0;
}

E

不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。不要读错题。下回你就没有 5 min 切的运气了。


发现每一堆石子之间互相独立,因此考虑分别计算其 SG 函数的值然后异或。首先可以写出暴力 O(n) 计算 SG 值程序打表,然后可以发现如下的规律:

  • SG(x)=02x
  • SG(x)=1x=1
  • SG(x)=IDxxPrime
  • SG(x)=mini=1kIDvi,满足 k2i=1kvi=xviPrime

因此可以使用重科技 Pollard-Rho 分解质因数,也可以一遍线性筛素数计算出每一个 x 的最大质因数然后每一次除以这个数得到其所有的质因子。因此做完了。

const int N=10000010;
int a[N],n,Sg[10000005],FR[N];
int id[10000005];
int prime[N], tot;
bool np[N];
void sieve(int maxn) {
    np[1] = true;
    for (int i = 2; i <= maxn; i++) {
        if (!np[i]) {
            prime[++tot] = i;
            id[i]=tot;
            FR[i]=i;
        }
        for (int j = 1; j <= tot && i * prime[j] <= maxn; j++) {
            np[i * prime[j]] = true;
            FR[i*prime[j]]=prime[j];
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
}
int SG(int x){
    if(~Sg[x])return Sg[x];
    if(x%2==0)return 0;
    if(x==1)return 1;
    if(!np[x])return id[x];
    int mi=1e9;
    while(x>1){
        mi=min(mi,id[FR[x]]);
        x/=FR[x];
    }
    return mi;
}
signed main(){
    memset(Sg,-1,sizeof Sg);
    Sg[0]=0;
    sieve(N-9);
    int T;cin>>T;
    while(T--){
        cin>>n;
        F(i,1,n)cin>>a[i];
        int sg=0;
        F(i,1,n)sg^=SG(a[i]);
        if(sg)cout<<"Alice\n";
        else cout<<"Bob\n";
    }
    return 0;
}

F

不太会的题。看到 n2000 和区间问题想到区间 dp。设 fi,j 表示问 ij 一段区间中所需要的最小的操作次数。则容易发现 2 操作完全迷惑人没有任何用途,只需要暴力转移 1 操作即可。

si=j=1iaiMapi 表示出现 i 值的时候对答案造成的最小贡献是多少。

具体转移有:

  • 1fi,j=ji
  • 2fi,j=ji+Mapsi1+sj

然后更新 Mapsi1+sj 的值即可。

时间复杂度为 O(n2) 或者 O(n2logn)

const int N=500100;
int a[N],s[N];
int f[3010][3010];
signed main(){
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        F(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
        map<int,int>mp;
        G(i,n,1)F(j,i-1,n){
            if(j!=i-1){
                f[i][j]=j-i;
                if(mp.count(s[i-1]+s[j]))
                    f[i][j]=min(f[i][j],mp[s[i-1]+s[j]]+(j-i));
            }else f[i][j]=0;
            if(!mp.count(s[i-1]+s[j]))
                mp[s[i-1]+s[j]]=f[i][j]-j+i-2;
            else
                mp[s[i-1]+s[j]]=min(mp[s[i-1]+s[j]],f[i][j]-j+i-2);
        }
        int sum=0;
        F(i,1,n)F(j,i-1,n)sum+=f[i][j];
        cout<<sum<<'\n';
    }
    return 0;
}

G

完全不会做。咕咕咕。

posted @   yhbqwq  阅读(141)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示