[Poi2014]Couriers
查询区间内部数字出现次数大于(r-l+1)/2的数字
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #define LL long long #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) using namespace std; const int maxx = 500005; struct node{ int l,r,val; }tree[maxx*40]; int root[maxx]; int cnt; void inserts(int l,int r,int pre,int &now,int pos,int val){ now=++cnt; ///更新新节点的编号 tree[now]=tree[pre]; ///复制原来的节点的信息 tree[now].val+=val; ///更新新节点的信息 节点信息包括区间内部数字出现的次数 if (l==r){ return; } int mid=(l+r)>>1; if (pos<=mid) inserts(l,mid,tree[pre].l,tree[now].l,pos,val); else inserts(mid+1,r,tree[pre].r,tree[now].r,pos,val); } int query(int L,int R,int l,int r,int w){ if (l==r){ return l; } int mid=(l+r)>>1; ///如果节点的左子树中总的出现次数大于(r-l+1)/2 那么答案一定在左子树 if((tree[tree[R].l].val-tree[tree[L].l].val)>w){ return query(tree[L].l,tree[R].l,l,mid,w); }else if((tree[tree[R].r].val-tree[tree[L].r].val)>w){ ///否则在右子树 return query(tree[L].r,tree[R].r,mid+1,r,w); } return 0; } int main(){ int n,m,w; while(~scanf("%d%d",&n,&m)){ cnt=0; rep(i,1,n){ scanf("%d",&w); inserts(1,n,root[i-1],root[i],w,1); } int l,r; while(m--){ scanf("%d%d",&l,&r); printf("%d\n",query(root[l-1],root[r],1,n,(r-l+1)>>1)); } } return 0; }
有不懂欢迎咨询
QQ:1326487164(添加时记得备注)