CodeForce Round 215 DIV2 C 使用了线段树 但是多此一举...

这道题的题意蛮复杂,但是抽象出来就是统计一下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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值