[CF补题计划]Educational Codeforces Round 132 (Rated for Div. 2) A~D

碎碎念:

下午有点食物中毒,突发恶疾之后睡了四个多小时醒来好了- -,多校没打,秉承着反正有队友的摆烂心态结果队友也没打啊啊啊啊
尽量修一下代码美观度,打了快一年了还是萌新码风呜呜呜

A. Three Doors

#include<bits/stdc++.h>
using namespace std;
int a[4];
bool st[4];
main()
{
	int t,n;cin>>t;
	while(t--)
	{
		memset(st,0,sizeof st);
		cin>>n;
		int now=n;
		bool flag=1;

		for(int i=1;i<=3;i++) cin>>a[i];
		for(int i=1;i<=3;i++) st[now]=1,now=a[now];
		for(int i=1;i<=3;i++) if(!st[i]) flag=0;

		if(flag) cout<<"YES";
		else cout<<"NO";
		puts("");
	}
}

B. Also Try Minecraft

开了两个前缀和,sum[i]表示从1跳到i的摔落伤害,fsum[i]表示从n跳到i的摔落伤害(虽然不知道有没有必要)。
每次玩minecraft都要把shift切输入法的快捷键关掉- -但是不用shift写代码又会不趁手,只能来来回回开开关关orz

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
const int N=1e5+100;
int sum[N],fsum[N],a[N];
main()
{

	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(i>1&&a[i]<a[i-1]) sum[i]=abs(a[i]-a[i-1]);
	}
	
	for(int i=n;i>=1;i--) if(i<n&&a[i]<a[i+1]) fsum[i]=abs(a[i+1]-a[i]);
	for(int i=1;i<=n;i++) sum[i]+=sum[i-1];
	for(int i=n;i>=1;i--) fsum[i]+=fsum[i+1];
	
	int ans=0;
	while(m--)
	{
		int l,r;cin>>l>>r;
		if(l<r) ans=sum[r]-sum[l];
		else ans=fsum[r]-fsum[l];
		cout<<ans<<'\n';
	}
 }

C. Recover an RBS

太痛了,代码写得太丑了
参了题解的贪心,对于一个括号序列,尽量把'('往左填,使所有填出来的'('都在')'的左边,这样能使每个'('有更多的匹配')'的可能,合法的可能性最大。
那么合法可能性第二大的就是把最后一个填'('的地方填')',第一个填')'的地方填'('。
如果没有填'('或者没有填')',那一定说明只有一种填充方式,否则按照第二大可能性的方式填充,然后检验一下填充后序列是否合法,判断输出即可。

#include<bits/stdc++.h>
using namespace std;
int t;string s;
main()
{
	cin>>t;
	while(t--)
	{
		cin>>s;
		int l=0,need=s.size()/2;
		int len=s.size();
		for(int i=0;i<len;i++)
			if(s[i]=='(') l++;

		int d=0x3f3f3f3f,e=d;
		for(int i=0;i<len;i++)
		{
			if(s[i]=='?')
			{
				if(l>need) s[i]=')';
				if(l==need) s[i]=')',l++,e=i;
				if(l==need-1) l=need,s[i]='(',d=i;
				if(l<need) s[i]='(',l++;
			}
		}
		int cnt=0,flag=1;

		if(d!=0x3f3f3f3f&&e!=0x3f3f3f3f) s[d]=')',s[e]='(';
		else flag=0;

		for(int i=0;i<len;i++)
		{
			if(s[i]=='(') cnt++;
			else if(s[i]==')')cnt--;
			if(cnt<0) flag=0;
		}
		if(flag) cout<<"NO";
		else cout<<"YES";
		cout<<'\n';
	}
}

D. Rorororobot

D的过题人数比C多好多……板子真好抄.jpg
起始点可以走到终点,当且仅当:

  1. 起始点和终点之间的横向距离和纵向距离都能被k整除
  2. 设起始点和终点之间的最高障碍物高度为mx,找到离n最近的一个高度x,使(x-起始点高度)|k,则x>mx

mx涉及到区间最值,可以用线段树或者st表整一个,这里偷懒抄了线段树板子
O(n)判断mx大小会t5,打了线段树但不关输入输出同步流会t13,囧

#include<bits/stdc++.h>

using namespace std;
int n,m,k;
const int N=2e5+100;
int a[N];
struct seg{
	int l,r;
	int mx;
}t[N*4];

void build(int p,int l,int r)
{
	t[p].l=l,t[p].r=r;
	if(l==r) {t[p].mx=a[l];return;}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].mx=max(t[p*2].mx,t[p*2+1].mx);
}

int ask(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r) return t[p].mx;
	int mid=(t[p].l+t[p].r)/2;
	int val=-0x3f3f3f3f;
	if(l<=mid) val=max(val,ask(p*2,l,r));
	if(r>mid) val=max(val,ask(p*2+1,l,r));
	return val;
}

main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
		cin>>a[i];

	build(1,1,m);
	int q;cin>>q;
	while(q--)
	{
		int xs,ys,xf,yf;cin>>xs>>ys>>xf>>yf>>k;
		bool flag=1;
		if(abs(xf-xs)%k!=0) flag=0;
		if(abs(yf-ys)%k!=0) flag=0;
		int f=max(ys,yf),s=min(ys,yf);
		int mx=ask(1,s,f);
		int time=(n-xs)/k;
		if(xs+time*k>mx&&flag==1) puts("YES");
		else puts("NO");
	}
 }

不想睡觉再补场div2&学学Segment TRRRRREE(发出俄罗斯弹舌音)

posted @ 2022-07-31 03:09  Hssliu  阅读(22)  评论(0)    收藏  举报