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=。
设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;
}