2022年第三届辽宁省大学生程序设计竞赛

比赛经历:感觉辽宁省赛都比较抽象不建议写

目录

A.伟大奋斗

B.可莉的五子棋 

C.消除死域点

E.病毒危机

F.互质

G.栈与公约数

I.图的分割

M.画画


A.伟大奋斗

简单签到

void solve(){
     
    cin>>n;
    cout << n-1949 << endl;
    return ;
}

B.可莉的五子棋 

直接暴力找四个方向或者是永bfs去扩展四个方向

char s[M][M];
 
void solve(){
     
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>s[i][j];
     
    auto get = [&](char op){
         
        int ans = 0;
        vector l(n+5,vector<int>(m+5));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                l[i][j] = s[i][j] == op ? l[i][j-1] + 1 : 0;
                if(l[i][j]>=5) ans++;
            }
         
        vector d(n+5,vector<int>(m+5));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                d[i][j] = s[i][j] == op ? d[i-1][j] + 1 : 0;
                if(d[i][j]>=5) ans++;
            }
         
        vector lx(n+5,vector<int>(m+5));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                lx[i][j] = s[i][j] == op ? lx[i-1][j-1] + 1 : 0;
                if(lx[i][j]>=5) ans++;
            }
         
        vector rx(n+5,vector<int>(m+5));
        for(int i=1;i<=n;i++){
            for(int j=m;j>=1;j--){
                rx[i][j] = s[i][j] == op ? rx[i-1][j+1] + 1 : 0;
                if(rx[i][j]>=5) ans++;
            }
        }
        return ans;
    };
     
    cout << get('1') << ' ' << get('2') << endl;
    return ;
}

C.消除死域点

发现删除当前这条链只会对从当前节点到头结点这链的点有贡献所以可以用树装数组维护可以活的点

vector<int> g[N];
int sz[N],tr[N];
int ans,res;
void add(int k,int x){
    for(int i=k;i<=n;i+=lowbit(i)) tr[i]+=x;
}
int query(int k){
    int res = 0;
    for(int i=k;i;i-=lowbit(i)) res += tr[i];
    return res;
}
void dfs1(int u,int fa){
    sz[u] = 1;
    for(auto&v:g[u]){
        if(v==fa) continue;
        dfs1(v,u);
        sz[u] += sz[v];
    }
}
 
void dfs2(int u,int fa){
    if(sz[u]>m) add(sz[u],1);
    for(auto&v:g[u]){
        if(v==fa) continue;
        int now = ans-query(m+sz[v]); // 表示原来是死的也就是sz[u]=m+1 要减去
        res = min(res,now);
        dfs2(v,u);
    }
    if(sz[u]>m) add(sz[u],-1);
}
void solve(){
    
    cin>>n>>m;
    for(int i=1;i<n;i++){
        int a,b; cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs1(1,-1);
    ans = 0;
    for(int i=1;i<=n;i++) ans += (sz[i]-1)>=m; // 初始的时候有多少个死的
    res = ans;
    dfs2(1,-1);
    cout << res << endl;
    return ;
}

E.病毒危机

简单模拟即可

vector<int> g[N];
vector<int> pos;
bool st[N];
void solve(){
     
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int t; cin>>t;
        while(t--){
            int x; cin>>x;
            if(i==1) pos.push_back(x);
            else g[x].push_back(i);
        }
    }
    for(auto&x:pos)
        for(auto&v:g[x]) 
            st[v]=true;
     
    int ans = 0;
    st[1]=true;
    for(int i=1;i<=n;i++) ans += st[i];
    cout << ans << endl;
    return ;
}

F.互质

感性分享一下就是暴力即可
 

void solve(){
    
    LL x; cin>>x;
    LL L = (x+3)/4, R = x/2;
    while(L<=R){
        if(__gcd(L,x)==1){
            cout << L << endl;
            return ;
        }
        L++;
    }
    cout << -1 << endl;
    return ;
}

G.栈与公约数

典型的区间修改直接上线段树

vector<int> a;
int idx;
int w[N];
struct code{
    int l,r;
    int x;
    int tag;
}tr[4*N];
 
void pushup(code&u,code&l,code&r){
     u.x = __gcd(l.x,r.x);
}
void pushdown(code&u,code&l,code&r){
     if(u.tag){
         l.x = u.tag,l.tag = u.tag;
         r.x = u.tag,r.tag = u.tag;
         u.tag = 0;
     }
}
 
void pushup(int u){
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
 
void pushdown(int u){
     pushdown(tr[u],tr[u<<1],tr[u<<1|1]);
}
 
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
        return ;
    }
    tr[u]={l,r};
    int mid=l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    pushup(u);
}
 
void modify(int u,int l,int r,int x){
    if(tr[u].l>= l && tr[u].r<=r){
        tr[u].x = x;
        tr[u].tag = x;
        return ;
    }
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid) modify(u<<1,l,r,x);
    if(r>mid) modify(u<<1|1,l,r,x);
    pushup(u);
}
 
code query(int u,int l,int r){
    if(tr[u].l>=l && tr[u].r<=r){
        return tr[u];
    }
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(r<=mid) return query(u<<1,l,r);
    else if(l>mid) return query(u<<1|1,l,r);
    else{
        code res;
        code ll=query(u<<1,l,r);
        code rr=query(u<<1|1,l,r);
        pushup(res,ll,rr);
        return res;
    }
}
void solve(){
     
    cin>>n;
    build(1,1,n);
    while(n--){
        int op,x; cin>>op;
        if(op==1){
            cin>>x;
            ++idx;
            modify(1,idx,idx,x);
        }
        else if(op==2){
            --idx;
        }
        else if(op==3){
            code t = query(1,idx,idx);
            cout << t.x << endl;
        }
        else{
            cin>>x;
            code t = query(1,idx-x+1,idx);
            modify(1,idx-x+1,idx,t.x);
        }
    }
    return ;
}

I.图的分割

搞懂题目意思其实就是最大生成树的最后一条边

struct code{
    int a,b,w;
    bool operator<(const code&t)const{
        return w>t.w;
    }
}e[N];
int p[N];
int find(int x){
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
void solve(){
    
    cin>>n>>m;
    for(int i=1;i<=n;i++) p[i]=i;
    for(int i=1;i<=m;i++){
        int a,b,w; cin>>a>>b>>w;
        e[i]={a,b,w};
    }
    sort(e+1,e+1+m);
    int cnt = 0;
    for(int i=1;i<=m;i++){
        auto [a,b,w]=e[i];
        int fa=find(a),fb=find(b);
        if(fa!=fb){
            cnt++;
            if(cnt==n-1){
                cout << w << endl;
                return ;
            }
            p[fa]=fb;
        }
    }
    return ;
}

M.画画

简单画一画找找规律即可

void solve(){
     
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            s[i][j]=1;
     
    int x,y;
    if(n&1) x = 1,y = 1;
    else x = 2, y = 2;
         
    while(x<=n and y<=n){
        s[x][y]=0;
        x += 2, y += 2;
    }
     
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++) 
            cout << s[i][j];
        cout << endl;
    }
    return ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值