Codeforces Round #578 (Div. 2)

A. Hotelier(水题)

题意:有0-9号,10个房间,客人可以从左边进,右边进,L代表从左边进,R代表从右边进,0-9代表该房间的客人离开,从左右进的都选择住离入口最近的,然后

问在操作结束后每个房间是否还有人。

题解:遍历一遍就行了~

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
bool vis[maxn];
int main(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    int l=0,r=9;
    memset(vis,0,sizeof(vis));
    for(int i=0;i<s.size();i++){
        if(s[i]=='L'){
            for(int j=0;j<=9;j++){
                if(!vis[j]){
                    vis[j]=true;
                    break;
                }
            }
        }
        else if(s[i]=='R'){
            for(int j=9;j>=0;j--){
                if(!vis[j]){
                    vis[j]=true;
                    break;
                }
            }
        }
        else vis[s[i]-'0']=false;
    }
    for(int i=0;i<=9;i++){
        if(vis[i])cout<<1;
        else cout<<0;
    }
    cout<<endl;
    return 0;
}
View Code

B. Block Adventure

题意:你可以 上/下 的高度为k,然后你有一个背包,可以装下当前位置的所有可以拿的砖头,问你是否能到达最后一个高度;

题解:贪心,能拿的砖尽量拿,然后用最少的砖去上,拿最多的砖去下;遇到包里的所有都拿出来垫还不能爬上就NO

wa在漏掉了 当前位置的砖头拿多了~~变为负的了,应该到0就停止,写的有点麻烦,懒得再写一遍了

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll a[maxn];
ll b[maxn];
int main(){
    int T;
    cin>>T;
    while(T--){
        ll n,m,k;
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=2;i<=n;i++){
            b[i]=a[i]-a[i-1];
        }
        int flag=1;
        for(int i=2;i<=n;i++){
            if(b[i]>=0){
                if(b[i]>m+k){
                    flag=0;
                    break;
                }
                else{
                    if(b[i]<=k){
                        if(a[i-1]<=k-b[i])
                            m+=a[i-1];
                        else m+=(k-b[i]);
                    }
                    else {
                        m-=(b[i]-k);
                    }
                }
                if(m<0){
                    flag=0;
                    break;
                }
            }
            else {
                if(a[i]-k<=0){
                    m+=a[i-1];
                }
                else {
                    if(a[i]<=k)
                    m+=a[i-1];
                    else m+=a[i-1]-(a[i]-k);
                }
            }
        }
        if(flag==0)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
 
    return 0;
}
View Code

C. Round Corridor

题意:有两个盘,内盘分为n份,外盘分为m份,然后问你能否从询问的sy走到ey;

赛时:当时想到gcd了,整体的思路是有的,但就是一直wa~透!然后就一直改,离正解越来越远

正解:gcd,然后把每一份的间隔求出来,然后在询问的时候求出sy和ey所在的块是否相同,如果不同就NO,相同就YES

注意:sy,ey要减减,因为在边界点是属于前一块的,这样能保证不会出现边界位置导致wa!!

#include <bits/stdc++.h>
using namespace std;
typedef  long long  ll;
int main(){
    ll n,m,q;
    cin>>n>>m>>q;
    ll gcd=__gcd(n,m);
    ll x=n/gcd;//
    ll y=m/gcd;//
    while(q--){
        ll sx,sy,ex,ey;
        cin>>sx>>sy>>ex>>ey;
        sy--,ey--;
        if(sx==1)sy/=x;
        else sy/=y;
        if(ex==1)ey/=x;
        else ey/=y;
 
        if(sy==ey)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
 
    return 0;
}
View Code

D. White Lines

题意:给你一个n*n的图,B表示黑色,W表示白色,你可以选择一个点,然后在iii+k1i≤i′≤i+k−1 and jjj+k

区间内所有的点都变为白色,问最多能有多少行和列在操作之后全为白色;

自己:看了半天学长的代码,没看懂,回宿舍问了一下,慢慢的就懂了,还是太笨了把~~

正解:统计i,j从1到n-m+1,每一个点用sum[i][j]来记录会使得满足题意的行列增加的个数,sum[i][j]都是依赖于前一个状态的,MAX[i][j]要用前缀和思想来记录;

行跑一边,列跑一边,MAX[i][j]就记录着在i,j点满足最多题意的白色行列,取最大值加上已经存在的ans就是答案了~;

#include <bits/stdc++.h>
using namespace std;
const int maxn=2100;
char g[maxn][maxn];
int res[maxn][maxn],sum[maxn][maxn];
int MAX[maxn][maxn];
int ans=0;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",g[i]+1);
        for(int j=1;j<=n;j++){
            if(g[i][j]=='W'){
                res[i][j]=res[i][j-1]+1;
            }
            else res[i][j]=res[i][j-1];
        }
        if(res[i][n]==n)ans++;
        for(int j=1;j<=n-m+1;j++){
            sum[i][j]=sum[i-1][j];
            if((res[i][n]-res[i][j+m-1]+res[i][j-1]==n-m)&&(res[i][j+m-1]-res[i][j-1]!=m)){
                sum[i][j]++;//记录当前这个位置如果被替换的话,满足的行会不会增加
            }
        }
    }
    for(int i=1;i<=n-m+1;i++){
        for(int j=1;j<=n-m+1;j++){
            MAX[i][j]=sum[i+m-1][j]-sum[i-1][j];//记录替换i,j点时符合条件的值;
        }
    }
    memset(res,0,sizeof(res));
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(g[j][i]=='W'){
                res[j][i]=res[j-1][i]+1;
            }
            else res[j][i]=res[j-1][i];
        }
        if(res[n][i]==n)ans++;
        for(int j=1;j<=n-m+1;j++){
            sum[j][i]=sum[j][i-1];
            if((res[n][i]-res[j+m-1][i]+res[j-1][i]==n-m)&&(res[j+m-1][i]-res[j-1][i]!=m)){
                sum[j][i]++;
            }
        }
    }
 
    for(int i=1;i<=n-m+1;i++){
        for(int j=1;j<=n-m+1;j++){
            MAX[i][j]+=sum[i][j+m-1]-sum[i][j-1];
        }
    }
    int maxx=0;
    for(int i=1;i<=n-m+1;i++){
        for(int j=1;j<=n-m+1;j++){
            maxx=max(maxx,MAX[i][j]);
        }
    }
    cout<<maxx+ans<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/lin1874/p/11343464.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值