终榜:
A:
题目:
有三扇门和其中一个门的钥匙,每个门后面可能有其他门的钥匙,问能否将三扇门全部打开
思路:
暴力即可
#include
using namespace std;
#define ll long long
#define T()\
int tt; \
cin>>tt; \
while(tt--)
#define endl "\n"
const int N=105;
int a[N];
int main()
{
T()
{
int x;
cin>>x;
for(int i=1;i<=3;i++)cin>>a[i];
int ct=1;
while(a[x])//如果当前的钥匙还能继续开门
{
ct++;
x=a[x];
}
if(ct==3)puts("YES");//如果开了三扇门
else puts("NO");
}
}
B:
题目:
给定n座山的高度以及m次询问
每次询问给定一个l和r(l有可能大于r)
每次你从坐标为 l 的山出发到达坐标为 r 的山,如果你路径上的下一座山比当前山高的话不耗费体力,否则耗费 高度差 的体力,问每次耗费多少
思路:做一个简单的预处理即可
#include
using namespace std;
#define ll long long
#define T()\
int tt; \
cin>>tt; \
while(tt--)
#define endl "\n"
const ll mod=1e9+7;
const int N=2e6+10;
ll a[N];
ll cnt1[N],cnt2[N];
int main()
{
// T()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=2;i<=n;i++)
{
if(a[i]>=a[i-1])cnt1[i]=cnt1[i-1];//预处理从前到后的山
else cnt1[i]=cnt1[i-1]+(a[i-1]-a[i]);
}
cnt2[n]=0;
for(int i=n-1;i>=1;i--)
{
if(a[i]>=a[i+1])cnt2[i]=cnt2[i+1];//预处理从后到前的山
else cnt2[i]=cnt2[i+1]+(a[i+1]-a[i]);
}
while(m--)
{
int l,r;
cin>>l>>r;
if(l<=r)
{
cout<
C:
题目:
给定一个字符串,里面含有 '(' , ')' , '?'三种字符,‘?’可以变成任意的括号(左括号或右括号),问组成合法括号序列的方法是否唯一,
如果唯一打印“YES”,否则打印“NO”,题目保证数据一定有一组解
合法括号定义:设‘(’的数量为a,‘)’的数量为b,对于任意的i,都有a>=b。
思路:
我们可以发现,如果当前序列中 ‘ (’的数量已经为总长度(下面设为 L )的一半了,那么解法一定唯一,如果没有满足上述条件,那么对于前面某些个左括号,若解法唯一,他们一定是‘(’,下面给出证明。
证:对于‘(’数量不到 L /2 时,对于第一个‘?’,我们可以知道这个字符为‘(’时序列一定合法,因为这样可以尽最大可能满足合法括号定义,因此如果这个括号为‘)’时序列也合法,那么一定是多解,输出“NO”。
那么我们如何判断括号为‘)’时也合法呢?
我们只需要将前面的(L/2-a)个问号赋值成‘(’,并且把剩下的括号赋值成‘)’,然后我们交换最后一个通过‘?’转换成的左括号以及第一个通过‘?’转换成的右括号的位置,判断序列是否合法即可,如果合法,说明有多解,不然就是唯一解。
#include
using namespace std;
#define ll long long
#define T()\
int tt; \
cin>>tt; \
while(tt--)
#define endl "\n"
const int N=2e6+10;
int main()
{
T()
{
string s;
cin>>s;
int now=0;
for(int i=0;ipos;
for(int i=0;i
D:
题目:
给定一个n行m列的地图,接下来给定m个数,对于1<=i<=m,hi表示第m列的前hi行格子被堵塞,不能通过,即(1,m)~(hi,m)这hi个格子不能通过。
现给定Q次询问,每次询问给定一个起始坐标(qx,qy)以及终止坐标(zx,zy)以及一个k,
一个机器人从起始坐标出发前往终止坐标,可以走任意次,每次走的格子数量规定为k,并且是朝着同一个方向走k步,规定机器人不能走到地图外面,也不能通过被堵塞的格子,问能否到达目的地。(给定的起始坐标以及终止坐标没有被堵塞)
数据范围:1<=n<=1e9,1<=m<=2e5,0<=hi<=n,1<=Q<=2e5
思路:
通过线段树维护一个区间最大值(当然,ST表也行),我们可以让机器人每次都先走到当前列的尽可能靠后的一行(假设是sj),然后走到终止坐标的列,然后前往终止坐标的行,只要起始坐标的列到终止目标的列之间没有被堵塞即可到达,所以我们查询这段区间的最值,然后和sj比较即可,需要注意的是,由于题目中规定每次走的格子数量必须为k,所以有:
abs(qx-zx)%k==0&&abs(qy-zy)==0
#include
using namespace std;
#define ll long long
#define T()\
int tt; \
cin>>tt; \
while(tt--)
#define endl "\n"
const int N=2e6+10;
ll a[N];
struct node
{
ll l,r,val;
}tr[N<<2];
void build(int now,int l,int r)//建树
{
tr[now].l=l,tr[now].r=r;
if(l==r)
{
tr[now].val=a[l];
return;
}
int mid=l+r>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tr[now].val=max(tr[now<<1].val,tr[now<<1|1].val);
}
ll query(int now,int l,int r,int L,int R)//询问
{
if(L<=l&&r<=R)return tr[now].val;
ll ans=0;
int mid=l+r>>1;
if(mid>=L)ans=max(ans,query(now<<1,l,mid,L,R));
if(midzy)//保证起始坐标的列在终止坐标的列的前面
{
swap(qx,zx);
swap(qy,zy);
}
if(abs(zx-qx)%k!=0||abs(zy-qy)%k!=0)
{
puts("NO");
continue;
}
ll sj=qx+(n-qx)/k*k;//计算sj
ll zz=query(1,1,m,qy,zy);//查询区间[qy,zy]的最大值
if(zz>=sj)
{
puts("NO");
continue;
}
else puts("YES");
}
}
}