http://codeforces.com/contest/367/problem/A
题意:
给你一个字符串,你在其中找包含3个字符的连续的子串,再以任意顺序放回去,如果你不管放回多少次,每次都能找出不是“zyx” “yxz" "xzy"的这3种,那么这个字符串就是不合格的。
现在是给你一个字符串,m个询问,每个询问问你字符串从a位置到b位置的子串是不是合格的,合格的输出YES,不合格输出NO。
分析:
1. 如果你选出的字符串不足3个字符,那么你第一次就不能找出非上面的3种字符串(虽然上面的3种也不能找出),那么该字符串肯定是合格的。
2. 当选出的字符串大于3个字符时,首先犹豫是以任意的顺序放回去,那么该字符串的起始排列其实是没有任何价值的,唯一有价值的就是x,y,z分别的个数。
首先是x:y:z=1:1:1的时候,那么肯定是合格的,怎么才是不合格的呢?因为可以循环使用例如zyxz,这个字符串也是合格的,所以当其中一个比另外两个较少的那一个还多2个的话,那么这个串就是不合格的,否则就一定合格。
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 2147480000
struct hammer
{
int right,left;
int x;
int y;
int z;
}box[400401];
string s;
int sumx,sumy,sumz;
void build(int now,int l,int r)
{
box[now].left=l;box[now].right=r;
if(r==l)
{
if(s[l-1]=='x')
{
box[now].x=1;box[now].y=box[now].z=0;
}
else if(s[l-1]=='y')
{
box[now].y=1;box[now].x=box[now].z=0;
}
else if(s[l-1]=='z')
{
box[now].z=1;box[now].x=box[now].y=0;
}
}
else
{
int k=(r+l)/2;
build(now*2,l,k);
build(now*2+1,k+1,r);
box[now].x=box[now*2].x+box[now*2+1].x;
box[now].y=box[now*2].y+box[now*2+1].y;
box[now].z=box[now*2].z+box[now*2+1].z;
}
}
void qury(int a,int l,int r)
{
if(box[a].left==l && box[a].right==r)
{
sumx+=box[a].x;
sumy+=box[a].y;
sumz+=box[a].z;
}
else
{
int k=(box[a].right+box[a].left)/2;
if(k<l)
{
qury(a*2+1,l,r);
}
else if(k>=r)
{
qury(a*2,l,r);
}
else
{
qury(a*2,l,k);
qury(a*2+1,k+1,r);
}
}
}
int m;
int main(int argc, char *argv[])
{
cin>>s;
cin>>m;
build(1,1,s.size());
for(int i=1;i<=m;i++)
{
sumx=0;sumy=0;sumz=0;
int a,b;
scanf("%d%d",&a,&b);
if(b-a+1<3) cout<<"YES"<<endl;
else
{
qury(1,a,b);
int minn=inf;
minn=min(minn,sumx);
minn=min(minn,sumy);
minn=min(minn,sumz);
sumx-=minn;
sumy-=minn;
sumz-=minn;
if(sumx>=2 || sumy>=2 || sumz>=2)
{
cout<<"NO"<<endl;
}
else
{
cout<<"YES"<<endl;
}
}
}
return 0;
}