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; }