练习赛02

本文介绍了三个不同类型的算法问题及其解决方案。第一题涉及区域限制处理,通过设置最小值更新数组并计算平方和;第二题讨论双矩阵操作,通过贪心策略确定矩阵元素的取值;第三题是寻找隐藏与搜索的游戏策略,分析相邻位置的影响。这些题目展示了在处理有限制条件的数组操作和图形性质判断时的有效算法思路。
摘要由CSDN通过智能技术生成

传送门
A Zoning Restrictions Again
题解:有限制的点跟题中统一要求的取min,没有限制的点直接按照统一限制;
代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1000010;
int a[N];
void Test(){
	int n,h,m;
	cin>>n>>h>>m;
	for(int i=1;i<=n;i++) a[i]=h;
	while(m--){
		int l,r,x;
		cin>>l>>r>>x;
		for(int i=l;i<=r;i++) a[i]=min(a[i],x); 
	}
	int res=0;
	for(int i=1;i<=n;i++) res+=a[i]*a[i];
	cout<<res<<"\n";
}

int main() {
	ios::sync_with_stdio(false);
//	cin.tie(0);
	int t=1;
//	cin>>t;
//	int ncase=1;
	while(t--)
	Test(); 
	

}

/*
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
 
*/

B - Double Matrix

题解:可以有贪心得出,让一个矩阵取到两个矩阵同一位置的min,另一个取max,然后判断是否满足题意;
代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1010;
int a[N][N];
int b[N][N];
void Test(){
	int n,m;
	cin>>n>>m;
	int flag=0;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>b[i][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[i][j]<b[i][j]) swap(a[i][j],b[i][j]);
	for(int i=1;i<=n;i++) for(int j=1;j<m;j++) if(a[i][j]>=a[i][j+1]) flag=1;
	for(int i=1;i<=m;i++) for(int j=1;j<n;j++) if(a[j][i]>=a[j+1][i]) flag=1;
	for(int i=1;i<=n;i++) for(int j=1;j<m;j++) if(b[i][j]>=b[i][j+1]) flag=1;
	for(int i=1;i<=m;i++) for(int j=1;j<n;j++) if(b[j][i]>=b[j+1][i]) flag=1;
	if(flag) cout<<"Impossible\n";
	else cout<<"Possible\n";
}

int main() {
	ios::sync_with_stdio(false);
//	cin.tie(0);
	int t=1;
//	cin>>t;
//	int ncase=1;
	while(t--)
	Test(); 
	

}

/*
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
 
*/

C - Hide and Seek
题解:因为只能移动到相邻位置,并且只能移动一次,在所有对中,只有三种情况满足题意,即:(x,x-1) (x,x) (x,x+1); 然后check 这三种情况是否满足题意
对(x,x-1),以下三种情况满足任意一种就可以使答案加1:
若不存在 x 这个位置,可以一直停到x这个点 不移动 就可以满足题意,答案就加1;
若不存在 x-1 这个位置,则可以一开始就从x位置移动到 x-1 就可以满足题意,答案就加1;
若x和x-1都存在,则第一个 x 后面的位置都没有x-1,答案就加1,这里简单证明一下:因为一开始停在 x点,最优的方案是在即将到达x的时候移动到 x-1 ,然后就不能移动了,在这之后如果后面还存在 x-1 的话,就不符合题意。

对(x,x) 只有数组中不存在x的时候这一对才有贡献
对(x,x+1) 考虑方式跟对(x,x-1)一样;
还要注意一点,当x=1时,没有对(x,x-1),当x=n时,没有对(x,x-1);,详细见代码。
代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1000010;
int st[N],en[N];//st[i]表示i第一次出现的位置,en[i]数组代表i最后一次出现的位置
void Test(){
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=k;i++){
		int x;
		cin>>x;
		if(st[x]==0) st[x]=i;
		 en[x]=i;
	}
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(st[i]==0) cnt++;//判断对(x,x)
		int x=st[i];
		int y=en[i-1];
		if(i>1)
		if(y<=x||x==0||y==0) cnt++;//判断对(x,x-1)
		y=en[i+1];
		if(i<n)
		if(y<=x||x==0||y==0) cnt++;//判断对(x,x+1)
	}
	cout<<cnt;
}

int main() {
	ios::sync_with_stdio(false);
//	cin.tie(0);
	int t=1;
//	cin>>t;
//	int ncase=1;
	while(t--)
	Test(); 
	

}

/*
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
 
*/

D - Chladni Figure
题解:因为有 n 个位置 所以要想旋转k个位置后还与原图像重合,就相当于把原图形上的点移动k个位置,所有的点的连线情况与原图形相同,因为所有的点都是移动k个位置,所以所有满足题意的k必须是n的因子(可以手动模拟一下) 直接暴力check n的所有因子是否满足题意。假设x是n的因子 在check的x时候 可以把n个点全都逆时针移动x位,判断是否与原图形相同,就是判断所有点的连线情况,为了方便判断,可以把边的点按从小到大排序(相当于离散化),直接判断两个序列是否完全相同,若完全相同,就符合题意 。
因为判断的方法有很多种,也可以是vector储存,判断是可以直接判断v1==v2,但是当时想着时间复杂度比较大,就没有采用
详细见代码
代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1000010;
int prime[N];
bool st[N];
struct Node {
	int a,b;
}p[N],q[N];
bool cmp(Node a,Node b){
	if(a.a!=b.a) return a.a<b.a;
	return a.b<b.b;
}
void Test(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>p[i].a>>p[i].b;
		if(p[i].a>p[i].b) swap(p[i].a,p[i].b);//把原序列也排序,方便判断
	}
	sort(p+1,p+1+m,cmp);//对与对中也按从小到大,就是为了方便判断
	for(int i=1;i<n;i++){
		if(!(n%i==0)) continue;
		for(int j=1;j<=m;j++) {
			int x=p[j].a-i,y=p[j].b-i;//移动k各单位
			if(x<=0) x=n+x;
			if(y<=0) y=n+y;
			if(x>y) swap(x,y);
			q[j]={x,y};
		}
		sort(q+1,q+1+m,cmp);//也是离散化
		int flag=0;
		for(int j=1;j<=m;j++)
			if(p[j].a!=q[j].a||p[j].b!=q[j].b) flag=1;
		if(!flag) {//若两个序列全部相同,则符合答案
//			cout<<i<<"\n";
			cout<<"Yes";
			return ;
		}
	}
	cout<<"No\n";
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t=1;
//	cin>>t;
//	int ncase=1;
	while(t--)
	Test(); 
	

}

/*
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
 
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值