Codeforces Round #576 (Div. 2)部分题解

Welfare State
题意

有两个修改:1、将所有小于 x x x的改为 x x x。2、单点修改为 x x x

题解

比赛的做法:
维护最小最大值,最小小于 x x x就向下递归,最大小于 x x x直接区间修改。
但是如果一小一大的数据可以卡满复杂度。
赛后做法:
我们可以发现,对于一个点最后的大小等于最后一次修改过后和 2 2 2操作修改的比较。
我们记录每个操作过后最大的 2 2 2修改。
最后结果:初值/替换之后:修改与每次修改过后最大比较。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
typedef long long ll;
const int maxn = 3e5+200;
 
int n,m;
int bb[maxn],aa[maxn],cc[maxn];
 
struct node{
    int index,pos,val;
};
vector<node>vec;
 
int main(){
    cin>>n;
    FOR(i,1,n)scanf("%d",&aa[i]);
    cin>>m;
    FOR(i,1,m){
        int op,p,x;scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&p,&x);
            vec.push_back(node{i,p,x});
        }
        else{
            scanf("%d",&x);
            bb[i]=x;
        }
    }
    RFOR(i,m,1)cc[i]=max(cc[i+1],bb[i]);
    FOR(i,1,n)aa[i]=max(cc[1],aa[i]);
    for(auto it:vec){
        aa[it.pos]=max(it.val,cc[it.index]);
    }
    FOR(i,1,n)printf("%d ",aa[i]);
}
Matching vs Independent Set
题意

要求找到 n n n个边的匹配或者 n n n个点的独立集。图有 3 n 3n 3n个点
匹配是指任意两个没有公共点。独立集是指任意两个点没有边相连。

题解

如果我们直接暴力找 n n n条边,每次标记边的两个点,不重复选有相同点的,这样子一定能满足第一个。
如果找不到,说明标记的点不超过 2 n 2n 2n,剩下的点就可以构成第二个。
如果剩下点还有公共边的话,那么在第一步操作里一定还可以继续标记。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
typedef long long ll;
const int maxn = 5e5+200;
 
int x[maxn],y[maxn];bool vis[maxn];
int n,m;
int node[maxn],edges[maxn],tot;
 
int main(){
    int T;cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);n=3*n;
        FOR(i,1,m)scanf("%d%d",&x[i],&y[i]);
        FOR(i,1,n)vis[i]=false;
        tot=0;
        FOR(i,1,m)if(!vis[x[i]]&&!vis[y[i]]){
            vis[x[i]]=vis[y[i]]=true;
            edges[++tot]=i;
        }
        if(tot>=n/3){
            puts("Matching");
            FOR(i,1,n/3)printf("%d%c",edges[i],i==n/3?'\n':' ');
            continue;
        }
        tot=0;
        FOR(i,1,n)if(!vis[i]){
            vis[i]=true;
            node[++tot]=i;
        }
        if(tot>=n/3){
            puts("IndSet");
            FOR(i,1,n/3)printf("%d%c",node[i],i==n/3?'\n':' ');
            continue;
        }
    }
}
Rectangle Painting 1
题意

有一个矩形格子图,里面一部分黑色,一部分白色,每次可以把一个区域变成白色,花费是 m a x ( h , w ) max(h,w) max(h,w),问将所有格子涂成白色的最小花费。

题解

显然动规,但是太菜了没想出来(后面感觉懒的想了。
维护一个矩形的状态,那么一定是由小矩形形成的,但总不能枚举四维吧,这样加上大矩形,复杂度是 1 e 8 1e8 1e8。所以我们考虑分成两个操作,第一次竖着切,第二次横着切,这样在以后的操作也能够实现分割小矩形的操作,依然全面。
用记忆化搜索非常方便。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define RFOR(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
typedef long long ll;
const int maxn = 1e5+200;
 
int n;
int dp[55][55][55][55];
char s[55][55];
 
int dfs(int x1,int x2,int y1,int y2){
    if(x1==x2&&y1==y2)return s[x1][y1]=='#'?1:0;
    if(dp[x1][x2][y1][y2]!=-1)return dp[x1][x2][y1][y2];
    int &ret=dp[x1][x2][y1][y2];
    ret=max(y2-y1+1,x2-x1+1);
    FOR(i,x1,x2-1){
        ret=min(ret,dfs(x1,i,y1,y2)+dfs(i+1,x2,y1,y2));
    }
    FOR(i,y1,y2-1){
        ret=min(ret,dfs(x1,x2,y1,i)+dfs(x1,x2,i+1,y2));
    }
    return ret;
}
 
int main(){
    cin>>n;
    memset(dp,-1,sizeof(dp));
    FOR(i,1,n)scanf("%s",s[i]+1);
    dfs(1,n,1,n);
    cout<<dp[1][n][1][n]<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值