首页 > 其他分享 >CF370

CF370

时间:2024-10-30 12:42:22浏览次数:7  
标签:pii minn int sum CF370 maxn fi

废话

  1. 370:纪念盗笔青春

  2. 提交记录

几个脑残错误后文会提到

3.题目:
黄黄绿蓝蓝( 幸好 370 不是“红红红红红” | “黑黑黑黑黑” )
算法: 是没有滴 贪心,前缀和

正题

CF370A

Rook, Bishop and King

签到数学题

车可以两步到达任意点 ,只需判断出发点与目标点是否在同行 | 同列
王有个性质是每次可以同时改变行列,但不必须,所以答案即为横纵坐标的差的最大值
象必须每次同时改变行列,并不能到达所有点 ( 白格只能到白格 )所以判断奇偶输出 0 ,剩下的点与车同理

#include <bits/stdc++.h>
using namespace std;
int x1,y1,x2,y2;
int main(){
	cin>>x1>>y1>>x2>>y2;
	if(x1==x2||y1==y2)cout<<1<<" ";
	else cout<<2<<" ";
	if(y1-x1==y2-x2||y1+x1==y2+x2)cout<<1<<" ";
	else if((y1+x1)%2!=(y2+x2)%2)cout<<0<<" ";
	else cout<<2<<" ";
	cout<<max(abs(x2-x1),abs(y2-y1));
	return 0;
}

CF370B

Berland Bingo
签到 不知道是什么

对每个卡暴力判断子集即可,因为若其他卡是他的子集,那么消他的时候那个卡也会被消掉

#include <bits/stdc++.h>
using namespace std;
const int N=105;
int n,m[N],a[N][N],o[N],maxn;
bool flag=1;
bool check(int x){
	int cnt=0;
	for(int i=1;i<=m[x];i++){
		cnt+=o[a[x][i]];
	}
	if(cnt==m[x])return 0;
	return 1;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>m[i];
		for(int j=1;j<=m[i];j++){
			cin>>a[i][j];
			maxn=max(maxn,a[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		flag=1;
		for(int i=1;i<=maxn;i++)o[i]=0;
		for(int j=1;j<=m[i];j++)o[a[i][j]]=1;
		for(int j=1;j<=n;j++){
			if(i==j||m[j]>m[i])continue;
			if(!check(j)){
				cout<<"NO"<<endl;
				flag=0;
				break;
			}
		}
		if(flag)cout<<"YES"<<endl;
	}
	return 0;
}

CF370C

Mittens
题解全是错的,不要看

按照颜色数量排个序,发现左边换右边就行
发现若左边右边重合则同色
同色数量:2n-2o , o 为最大颜色数量

#include <bits/stdc++.h>
using namespace std;
const int N=5e3+3;
int n,m,a[N],p,cnt,o;
struct node{
	int x,num;
}e[N];
bool cmp(node a,node b){
	return a.x>b.x;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		if(a[i]!=a[i-1]){
			e[++cnt].num=a[i-1],e[cnt].x=p;
			o=max(o,p);
			p=0;
		}
		p++;
	}
	if(p)e[++cnt].num=a[n],e[cnt].x=p;
	o=max(p,o);
	if(o>n/2)cout<<2*n-2*o<<endl;
	else cout<<n<<endl;
	sort(e+1,e+1+cnt,cmp);
	n=0;
	for(int i=1;i<=cnt;i++)
		for(int j=1;j<=e[i].x;j++)a[n++]=e[i].num;
	for(int i=0;i<n;i++){
		cout<<a[i]<<" "<<a[(i+n/2)%n]<<endl;
	}
	return 0;
}

错误原因:if(p)e[++cnt].num=a[n],e[cnt].x=p;没加最后一个块

CF370D

Broken Monitor

注意:方框==正方形

所以正方形的边长能确定,就是\(max(maxx-minx,maxy-miny)\)

然后就直接枚举正方形的左上角判断是否所有 \(w\) 都在框上

如何判断是否所有 \(w\) 都在框上?
用二维前缀和!大正方形 - 比他小一圈的正方形 = 框

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2005;
int n,m,sum[N][N],minx=0x7f7f7f7f,miny=0x7f7f7f7f,maxx,maxy,edge,num;
char a[N][N];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+(a[i][j]=='w');
			if(a[i][j]=='w')num++,minx=min(minx,i),maxx=max(maxx,i),miny=min(miny,j),maxy=max(maxy,j);
		}
	}
	edge=max(maxx-minx,maxy-miny)+1;
	if(edge>min(n,m)){cout<<-1;return 0;}
//	cout<<num;
	for(int i=1;i+edge-1<=n;i++){
		for(int j=1;j+edge-1<=m;j++){
			int x1=i,y1=j,x2=i+edge-1,y2=j+edge-1,a1=x1+1,a2=x2-1,b1=y1+1,b2=y2-1;
			//if(i==1&&j==3)cout<<x1<<" "<<x2<<" "<<y1<<" "<<y2;
			if(edge>2){
				if(sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]==num){
					if(!(sum[a2][b2]-sum[a2][b1-1]-sum[a1-1][b2]+sum[a1-1][b1-1])){
						for(int k=1;k<=n;k++){
							for(int h=1;h<=m;h++){
								if(((k==x1&&(h<=y2&&h>=y1))||(k==x2&&(h<=y2&&h>=y1)))||((h==y1&&(k<=x2&&k>=x1))||(h==y2&&(k<=x2&&k>=x1))))
								{
									if(a[k][h]=='w')cout<<'w';
									else cout<<'+';
								}else cout<<'.';
							}
							cout<<endl;
						}
//						for(int k=1;k<=n;k++){
//							for(int h=1;h<=m;h++){
//								if(a)
//							}
//							cout<<endl;
//						}
						return 0;
					}
				}
			}else {
				if(sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]==num){
					for(int k=1;k<=n;k++){
						for(int h=1;h<=m;h++){
							if(((k==x1&&(h<=y2&&h>=y1))||(k==x2&&(h<=y2&&h>=y1)))||((h==y1&&(k<=x2&&k>=x1))||(h==y2&&(k<=x2&&k>=x1))))
							{
								if(a[k][h]=='w')cout<<'w';
								else cout<<'+';
							}else cout<<'.';
						}
						cout<<endl;
					}
					return 0;
				}
			}
		}
	}
	cout<<-1<<endl;
	return 0;
}

由提交记录得我挂了多次, 还好有拍子
错误:

  1. a[k][h] 写成 a[h][k]
  2. maxy=max(maxy,j) 写成 maxy=min(maxy,j)
  3. ! 不打 ()

我还是太菜了

CF370E

summer reading

cf 上的题解是 dp ,但我看不懂 ,洛谷的题解也像()一样,连代码都没有 ,故这里只讲我的贪心 ,( 有大佬会 dp 浇浇 )

记录一个 pair 的 minn maxn 表示使结果最小/最大的当前的数和量

于是可以由上一个转移过来

if(maxn[i-1].se>=2)maxn[i]=pii(maxn[i-1].fi+1,1);
else maxn[i]=pii(maxn[i-1].fi,maxn[i-1].se+1);
if(minn[i-1].se==5)minn[i]=pii(minn[i-1].fi+1,1);
else minn[i]=pii(minn[i-1].fi,minn[i-1].se+1);

目的就是判断可不可行 if(minn[i].fi>a[i]||maxn[i].fi<a[i])

到规定值时要手动修改值
maxn[i]=min(maxn[i],pii(a[i],5)); minn[i]=max(minn[i],pii(a[i],1));

手动修改值后
输出 直接取 maxn 即可

其实看代码更好理解

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
#define pii pair<int,int>
#define fi first
#define se second
pii minn[N],maxn[N];
int n,a[N],cnt[N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	if(a[1]>1){
		cout<<-1;
		return 0;
	}
	minn[1]=maxn[1]=pii(1,1);
	for(int i=2;i<=n;i++){
		if(maxn[i-1].se>=2)maxn[i]=pii(maxn[i-1].fi+1,1);
		else maxn[i]=pii(maxn[i-1].fi,maxn[i-1].se+1);
		if(minn[i-1].se==5)minn[i]=pii(minn[i-1].fi+1,1);
		else minn[i]=pii(minn[i-1].fi,minn[i-1].se+1);
		if(a[i]){
			if(minn[i].fi>a[i]||maxn[i].fi<a[i]){
			//	cout<<i;
				cout<<-1;
				return 0;
			}
			maxn[i]=min(maxn[i],pii(a[i],5));
			minn[i]=max(minn[i],pii(a[i],1));
		}
	//	cout<<maxn[i].fi<<" "<<maxn[i].se<<" "<<minn[i].fi<<" "<<minn[i].se<<endl;
	}
	if(maxn[n].se==1)maxn[n]=pii(maxn[n].fi-1,5);
	if(maxn[n]<minn[n]){
		cout<<-1<<endl;
		return 0;
	}
	cout<<maxn[n].fi<<endl;
	a[n]=maxn[n].fi;
	cnt[a[n]]=1;
	for(int i=n-1;i;i--){
	    a[i]=min(maxn[i].fi,a[i+1]); 
	    if(cnt[a[i]]==5)  a[i]--;//手动修改
	    cnt[a[i]]++;
	}
	for(int i=1;i<=n;i++)cout<<a[i]<<' ';
	return 0;
}

完结撒花

标签:pii,minn,int,sum,CF370,maxn,fi
From: https://www.cnblogs.com/Z-kazuha/p/18515631/kazuha370

相关文章