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<<' ';
}
}
}

浙公网安备 33010602011771号