atcoder beginner contest 420(ABCDEFG)

下午马蹄杯被吊打了:(

这场DE难度感觉偏简单,好像G过的比F多

A

题意:给定2个小于等于12的整数x,y,求x+y是星期几
思路:不知道为啥取模WA了,直接加完之后判断一下减12就好了

void solve(){
   int x,y;cin>>x>>y;
   x+=y;
   if(x>12){
    cout<<x-12<<endl;
   }else{
    cout<<x<<endl;
   }
}

B

题意:给定n个长度为m的01字符串,每一列代表一轮选举,按照题目给定的条件进行模拟,然后输出最后得分最高的那些人的编号(升序)

void solve(){
    int n,m;cin>>n>>m;
    vector<vector<int>>a(n+1,vector<int>(m+1));
    rep(i,1,n){
        rep(j,1,m)cin>>a[i][j];
    }
    int f=1;
    while(f){
        f=0;
    rep(i,1,n){
        rep(j,1,m){
            int mx=0;
            for(int z=0;z<4;z++){
                int nx=i+dx[z],ny=j+dy[z];
                if(nx<1||nx>n||ny<1||ny>m)continue;
                mx=max(mx,a[nx][ny]);
            }
            if(a[i][j]>mx){
                a[i][j]=mx;
                f=1;
            }
        }
    }
    }
    rep(i,1,n){
        rep(j,1,m){
            cout<<a[i][j]<<' ';
        }
        cout<<endl;
    }
}

C

题意:给定两个长度为n的数组,同时给定q个查询,每次查询修改ai或bi的值,求每次修改后所有的min(ai,bi)的值
思路:只要先预处理出原先的答案,然后每次查询在此基础上修改即可

void solve(){
    int n,q;cin>>n>>q;
    vector<int>a(n+1),b(n+1);
    rep(i,1,n)cin>>a[i];
    rep(i,1,n)cin>>b[i];
    int ans=0;
    rep(i,1,n){
        ans+=min(a[i],b[i]);
    }
    while(q--){
        char ch;cin>>ch;
        int x,v;cin>>x>>v;
        if(ch=='A'){
            ans-=min(a[x],b[x]);
            a[x]=v;
            ans+=min(a[x],b[x]);
        }else{
             ans-=min(a[x],b[x]);
            b[x]=v;
            ans+=min(a[x],b[x]);
        }
         cout<<ans<<endl;
    }
}

D

题意:给定一个nxm矩阵,.表示空,#表示障碍,S,G分别代表起点和终点,x表示关着的门,不可达,o表示开着的门,可达,?表示开关,每次遍历到?会时使所有的o变成x状态,x变成o状态

求S到G的最短路

思路:
对于矩阵图我们使用BFS求最短路
由于'?'开关的存在,需要使用一个二维的vis数组,0代表按下偶数次开关的矩阵遍历状态,1代表按下奇数次开关的矩阵遍历状态
代码方面需要注意一下,没写好会导致Wa或Tle

const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};
int n,m;
char g[505][505];
int vis[505][505][2];
struct node{
    int x,y;
    int s;
    int msk;
    node(){}
    node(int xt,int yt,int zt,int p){
        x=xt;
        y=yt;
        s=zt;
        msk=p;
    }
};
void solve(){
    cin>>n>>m;
    pii sx,ex;
    rep(i,1,n){
        rep(j,1,m){
            cin>>g[i][j];
            if(g[i][j]=='S')sx=mp(i,j);
            else if(g[i][j]=='G')ex=mp(i,j);
        }
    }
    queue<node>q;
   

    q.push(node(sx.fi,sx.se,0,0));

    while(q.size()){
        auto[x,y,step,msk]=q.front();q.pop();
        if(vis[x][y][msk])continue;
        vis[x][y][msk]=1;
        if(g[x][y]=='G'){
            cout<<step<<endl;return;
        }
        if(g[x][y]=='?')msk^=1;
        
        for(int i=0;i<4;i++){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx<1||nx>n||ny<1||ny>m)continue;
            if(g[nx][ny]=='#')continue;
            if(g[nx][ny]=='o'&&msk)continue;
            if(g[nx][ny]=='x'&&!msk)continue;
            if(vis[nx][ny][msk])continue;
            q.push(node(nx,ny,step+1,msk));
        }
    }
    cout<<-1<<endl;
}

E

题意:给定一个初始没有边的,但有n个白色点的图,查询有三种,分别为:
1.u,v之间连一条边
2.使u的状态切换(白变黑或黑变白)
3.判断u是否能够到达某个黑点
思路:并查集模拟一下即可,因为没有那种删边的操作,我们只需要维护每个连通块中find出来的老大的权值即可

vector<int>e[maxn];
int f[maxn];
int a[maxn];
int s[maxn];
int find(int x){
    if(f[x]!=x){
        f[x]=find(f[x]);
    }return f[x];
}
void merge(int x,int y){
    if(find(x)!=find(y)){
        s[find(y)]+=s[find(x)];
        f[find(x)]=find(y);
    }
}
void solve(){
    int n,q;cin>>n>>q;
    rep(i,1,n)f[i]=i;
    rep(i,1,q){
        int opt;cin>>opt;
        if(opt==1){
            int u,v;cin>>u>>v;
            merge(u,v);
        }else if(opt==2){
            int v;cin>>v;
            if(a[v]==1){
                s[find(v)]--;
            }else s[find(v)]++;

            a[v]^=1;
        }else{
            int v;cin>>v;
            if(s[find(v)]){
                cout<<"Yes"<<endl;
            }else{
                cout<<"No"<<endl;
            }
        }
    }

}

F

题意:给定一个#,.矩阵,求.构成的矩形总数
思路:
枚举矩形的底边,然后枚举一列,按照穿过当前枚举列的矩形数量增加答案。
容斥预处理cnt[i][j]数组,表示大小为ixj的矩形一共有多少个子矩形
单调栈左边是第一个小于,右边是第一个小于等于,避免重复计数

int n,m,k;

void solve(){
    cin>>n>>m>>k;
    vector<vector<int>>h(n+5,vector<int>(m+5));
    vector<string>g(n+1);
    rep(i,1,n){
        cin>>g[i];
        g[i]=" "+g[i];
    }
    rep(i,1,n){
        rep(j,1,m){
            if(g[i][j]=='#')h[i][j]=0;
            else{
                h[i][j] = h[i-1][j] + 1; 
            }
        }
    }

    vector<vector<int>>cnt(n+5,vector<int>(m+5));
    rep(i,1,n)rep(j,1,m){
        if(i*j<=k)cnt[i][j]=1;
    }
    rep(i,1,n){
        rep(j,2,m){
            cnt[i][j] = cnt[i][j] + 2*cnt[i][j-1] -cnt[i][j-2];
        }
    }
    rep(i,1,n){
        rep(j,1,m){
            cnt[i][j]+=cnt[i-1][j];
        }
    }

    int ans=0;
    rep(i,1,n){
        stack<int>stk;
        vector<int>L(m+1),R(m+1);
        for(int j=m;j>=1;j--){
            while(stk.size()&&h[i][stk.top()]>h[i][j]){
                L[stk.top()]=j+1;
                stk.pop();
            }
            stk.push(j);
        }
        while(stk.size()){
            L[stk.top()]=1;
            stk.pop();
        }

        for(int j=1;j<=m;j++){
            while(stk.size()&&h[i][stk.top()]>=h[i][j]){
                R[stk.top()] = j -1;
                stk.pop();
            }
            stk.push(j);
        }
        while(stk.size()){
            R[stk.top()] = m;
            stk.pop();
        }

        rep(j,1,m){
            ans+=cnt[h[i][j]][j-L[j]+1+R[j]-j] - cnt[h[i][j]][j-L[j]] - cnt[h[i][j]][R[j]-j];
        }
    }

    cout<<ans<<endl;
}

G

题意:求使得sqrtl(nxn+n+x)=mxm的n个数

思路:令(2n+1)^2 - (2m)^2 =1-4x,对1-4x分解因数

void solve(){
    int x;cin>>x;
    x=1-4*x;
    if(x>=0){
    vector<int>v;
    for(int i=1;i*i<=x;i++){
        if(x%i==0){
            int A = i;
            int B = x/i;
            A--;
            B--;
            if(A%2==0&&B%2==0){
                A/=2;
                B/=2;
                v.pb((A+B)/2);
                v.pb(-1*(A+B)/2 -1);
            }
        }
    }
    sort(v.begin(),v.end());
    cout<<v.size()<<endl;
    for(auto s:v){
        cout<<s<<' ';
    }
    }else{
        vector<int>v;
        int y=abs(x);
        for(int i=1;i*i<=y;i++){
            if(y%i==0){
                int A=i;
                int B=y/i;
                if((A-B-2)%4==0){
                    v.pb((A-B-2)/4);
                }
                B=i;
                A=y/i;
                if((A-B-2)%4==0){
                    v.pb((A-B-2)/4);
                }
            }
        }

        cout<<v.size()<<endl;
        sort(v.begin(),v.end());
        for(auto s:v){
            cout<<s<<' ';
        }
    }
}
posted @ 2025-08-24 22:35  Marinaco  阅读(16)  评论(0)    收藏  举报
//雪花飘落效果