[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
起始点可以走到终点,当且仅当:
- 起始点和终点之间的横向距离和纵向距离都能被k整除
- 设起始点和终点之间的最高障碍物高度为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(发出俄罗斯弹舌音)

浙公网安备 33010602011771号