bzoj2223[Coci 2009] PATULJCI

题目链接:bzoj2223

题目大意:

给一个N个数的序列,M次询问,每次询问一个区间[l,r]内是否有某个数出现次数大于(r-l+1)/2,如果存在则输出这个数,否则输出no。


题解:

整体二分

二分答案mid(就是那个数),如果某个询问区间里所有小于等于mid的数的个数都不大于(r-l+1)/2的话,那么该区间的答案一定大于mid,所以划分到[mid+1,r]这个区间上,反之相反。然后这个就跟之前一样用树状数组维护就好了。

需要注意的一点是,最后当l=r时就不能再加小于等于mid的数了,必须要加入严格等于mid的数,这样才能判断是否有解


【啊二分要先考虑有没有单调性啊,某大大好机智%%%怎么说看完豁然开朗

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 350000

struct node
{
	int l,r,c,ans,tg;
}q[maxn];
int n,m,c[maxn],id[maxn];
int tol[maxn],tor[maxn];
int lowbit(int x) {return x&(-x);}
void change(int x,int k)
{
	for (x;x<=n;x+=lowbit(x)) c[x]+=k;
}
int query(int x)
{
	int ret=0;
	for (x;x>0;x-=lowbit(x)) ret+=c[x];
	return ret;
}
void solve(int head,int tail,int l,int r)
{
	if (head>tail) return;
	int i,lnum=0,rnum=0,mid=(l+r)>>1;
	if (l==r)
	{
		for (i=head;i<=tail;i++)
		  if (q[id[i]].tg==1 && q[id[i]].l==mid) change(q[id[i]].r,1);
		  else if (q[id[i]].tg==2)
		  {
			  int now=query(q[id[i]].r)-query(q[id[i]].l-1);
			  if (now>q[id[i]].c) q[id[i]].ans=l;
			  else q[id[i]].ans=-1;
		  }
		for (i=head;i<=tail;i++)
		  if (q[id[i]].tg==1 && q[id[i]].l==mid) change(q[id[i]].r,-1);
		return;
	}
	for (i=head;i<=tail;i++)
	  if (q[id[i]].tg==1)
	  {
		  if (q[id[i]].l<=mid) change(q[id[i]].r,1),tol[++lnum]=id[i];
		  else tor[++rnum]=id[i];
	  }
	  else
	  {
		  int now=query(q[id[i]].r)-query(q[id[i]].l-1);
		  if (now>q[id[i]].c) tol[++lnum]=id[i];
		  else tor[++rnum]=id[i];
	  }
	for (i=head;i<=tail;i++)
	  if (q[id[i]].tg==1 && q[id[i]].l<=mid) change(q[id[i]].r,-1);
	for (i=0;i<lnum;i++) id[head+i]=tol[i+1];
	for (i=0;i<rnum;i++) id[head+i+lnum]=tor[i+1];
	solve(head,head+lnum-1,l,mid);
	solve(head+lnum,tail,mid+1,r);
}
int main()
{
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int lim,t=0,i,x,y;
	scanf("%d%d",&n,&lim);
	for (i=1;i<=n;i++)
	{
		scanf("%d",&x);
		id[++t]=t;q[t].tg=1;
		q[t].l=x;q[t].r=i;
		q[t].ans=-1;
	}
	scanf("%d",&m);
	for (i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		id[++t]=t;q[t].tg=2;
		q[t].c=(y-x+1)/2;
		q[t].l=x;q[t].r=y;
		q[t].ans=-1;
	}
	solve(1,t,1,lim);
	for (i=1;i<=t;i++) 
	 if (q[i].tg==2) 
	 {
		 if (q[i].ans!=-1) printf("yes %d\n",q[i].ans);
		 else printf("no\n");
	 }
	return 0;
}


posted @ 2017-01-16 11:10  OxQ  阅读(114)  评论(0编辑  收藏  举报