这道题的题意蛮复杂,但是抽象出来就是统计一下xyz的个数分别是多少,如果最大相差不超过1,那么就可以,否则不可以。
阅读了一下其他人的代码,发现都是随便保存了一下前缀后缀什么的就过了。
所以,这种明显可以用线段树,但是找不到需要更新的地方的题目就不要用线段树了,保存一下“前缀和”,就可以O(1)的回答,线段树还要O(longn)
想起来长沙那道A题,别人过得那么快,自己过得那么慢就是因为弄复杂了,不是什么题都要用线段树的。
不过话说线段树还真是好用
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MAX_N 500000
int judge[MAX_N][3];
char a[MAX_N];
void PushUp(int rt)
{
for(int i=0;i<3;i++)
judge[rt][i]=judge[rt<<1][i]+judge[rt<<1|1][i];
}
void build(int l,int r,int rt)
{
if(l==r)
{
if(a[l-1]=='x')
judge[rt][0]=1;
if(a[l-1]=='y')
judge[rt][1]=1;
if(a[l-1]=='z')
judge[rt][2]=1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void query(int L,int R,int l,int r,int rt,int &x,int &y,int &z)
{
if(L>r||R<l)
{
x=y=z=0;
return;
}
if(L<=l&&r<=R)
{
x=judge[rt][0];
y=judge[rt][1];
z=judge[rt][2];
return ;
}
int m=(l+r)>>1;
int x1,y1,z1,x2,y2,z2;
query(L,R,lson,x1,y1,z1);
query(L,R,rson,x2,y2,z2);
x=x1+x2;
y=y1+y2;
z=z1+z2;
}
bool resolve(int x,int y,int z)
{
int a[3];
a[0]=x;
a[1]=y;
a[2]=z;
sort(a,a+3);
if(a[2]-a[0]>1)
return false;
return true;
}
int main()
{
scanf("%s",a);
int len=strlen(a);
build(1,len,1);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if(r-l<2)
{
puts("YES");
continue;
}
int x,y,z;
query(l,r,1,len,1,x,y,z);
if(resolve(x,y,z))
puts("YES");
else
puts("NO");
}
return 0;
}