Educational Codeforces Round 132 (Rated for Div. 2) A~D

比赛链接

A.题意:你从第x扇门进去,一共三扇门,每扇门后面有一把钥匙,然后钥匙为x打开第x扇门。

很显然,我们模拟就行了。

#include<iostream>
#include<vector>
using namespace std;
const int N=2e5+10;
int T,n,m;
void solve(){
	int x;cin>>x;
	int a[4]={0};
	cin>>a[1]>>a[2]>>a[3];
	int cnt=0;
	while(x){
		cnt++;
		x=a[x];
	}
	//cout<<cnt<<endl;
	if(cnt==3)cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
}
int main(){
	cin>>T;
	while(T--)
		solve();
	return 0;
}

B.题意:给定n个点的高度,然后从较高的点到较低的点有摔落伤害,给定任务区间,从l到r,求收到的摔落伤害即可。考虑处理每两点间的摔落伤害,正反各处理一遍,然后求前后缀和即可。不开long long见祖宗!!!!!

#include<iostream>
#include<cstring>
#include<vector>
#define int long long 
using namespace std;
const int N=2e5+10;
int T,n,m,a[N],d1[N],d2[N],s1[N],s2[N];
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	d2[n+1]=0;
	for(int i=1;i<n;i++)s1[i]=max(0ll,a[i]-a[i+1]);
	for(int i=n;i>1;i--)s2[i]=max(0ll,a[i]-a[i-1]);
	//for(int i=1;i<=n;i++)cout<<s1[i]<<' ';cout<<endl;
	//for(int i=1;i<=n;i++)cout<<s2[i]<<' ';cout<<endl;
	for(int i=1;i<=n;i++)d1[i]=d1[i-1]+s1[i];
	//for(int i=1;i<=n;i++)cout<<d1[i]<<' ';cout<<endl;
	for(int i=n;i>=1;i--)d2[i]=d2[i+1]+s2[i];
	for(int i=1;i<=m;i++){
		int l,r;
		cin>>l>>r;
		if(l<r){
			cout<<d1[r-1]-d1[l-1]<<endl;
		}
		else cout<<d2[r+1]-d2[l+1]<<endl;
	}
}
signed main(){
	solve();
	return 0;
	
}

C题意:给定合法的括号序列,但是将其中的一些括号换成了问号。题目保证至少有一种合法的括号序列。如果没有问号,我们可以很容易的判断一个括号序列是否合法,用栈模拟即可,相信这种方法大家应该都会。考虑有问好的情况,左括号是入栈,右括号是出栈,考虑维护一个变量tot:栈顶高度,now:当前出现的问好的数量,'('  就tot++ ,')'就tot--。'?'就now++

注意到如果tot<0,说明之前一定有一个'?'是’('。

如果tot=0,now=1,说明前面一定有一个‘?’是'('

如果最后tot==now,说明只有唯一的一个解,否则一定有多组解。

// LUOGU_RID: 142027093
#include<iostream>
#include<vector>
using namespace std;
const int N=2e5+10;
int T,n,m;
string a; 
void solve(){
	cin>>a;
	int dep=0,now=0;
	for(int i=0;i<a.length();i++){
		if(a[i]=='(')dep++;
		else if(a[i]==')')dep--;
		else now++;
		if(dep<0)dep++,now--;
		if(dep==0&&now==1)dep++,now--;//这个问号一定是'(' 
	}
	if(dep==now)cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
}
int main(){
	cin>>T;
	while(T--)
		solve();
	return 0;
}

D.题意:机器人只能一下子走k步,每列自底部开始的ai格有障碍(可别像我一样读错题了哦),问你能不能从起点(a,b)走到(c,d)。

首先考虑(c-a),(d-b)是不是k的倍数,若不是一定走不了。

我们发现,机器人在能走到的最高处的时候一定是被阻碍的概率是最小的,假设这个点的纵坐标是bmax.假设往上走了t步,则b+kt≤n,bmax=b+\frac{n-b}{k}*k

设ma是[a,c]阻拦高度的最大值。

如果ma>=bmax,说明走不了。

至于ma,可以考虑用st表,线段树,甚至分块(暴论)多种方式维护,我的线段树好像常数很大,加了快读才过。

// LUOGU_RID: 142080050
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e5+10;
int n,m,a[N],maxv[N<<2];
inline int read(){
	char ch = getchar();
	int x = 0, f = 1;
	while(ch < '0' || ch > '9'){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
void pushup(int id){
	maxv[id]=max(maxv[id<<1],maxv[id<<1|1]);
}
void build(int id,int l,int r){
	if(l==r){
		maxv[id]=a[l];
		return;
	}
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	pushup(id);
}
int query(int id,int l,int r,int x,int y){
	if(x<=l&&y>=r)return maxv[id];
	int mid=l+r>>1;
	int ans=0;
	if(x<=mid)ans=max(ans,query(id<<1,l,mid,x,y));
	if(y>mid)ans=max(ans,query(id<<1|1,mid+1,r,x,y));
	return ans;
}
int main(){
	n=read();
	m=read();
	for(int i=1;i<=m;i++)a[i]=read();
	build(1,1,m);
	int q;q=read();
	for(int i=1;i<=q;i++){
		int a,b,c,d,k;
		a=read();
		b=read();
		c=read();
		d=read();
		k=read();
		swap(a,b);
		swap(c,d);
		int ok=1;
		if(abs(a-c)%k!=0)ok=0;
		if(abs(b-d)%k!=0)ok=0;
		if(a>c)swap(a,c);
		//找到b当前的最高点
		b=b+(n-b)/k*k;
		int ma=query(1,1,m,a,c);
		if(b<=ma)ok=0;
		if(ok)cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值