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; }
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; }
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; }
D. White Lines
题意:给你一个n*n的图,B表示黑色,W表示白色,你可以选择一个点,然后在i≤i′≤i+k−1i≤i′≤i+k−1 and j≤j′≤j+k−1
区间内所有的点都变为白色,问最多能有多少行和列在操作之后全为白色;
自己:看了半天学长的代码,没看懂,回宿舍问了一下,慢慢的就懂了,还是太笨了把~~
正解:统计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; }