3524: [Poi2014]Couriers
Description
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
Input
第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。
Output
m行,每行对应一个答案。
Sample Input
7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6
Sample Output
1
0
3
0
4
0
3
0
4
HINT
【数据范围】
n,m≤500000
2016.7.9重设空间,但未重测!
/* 主席树处理+二分查找 几乎是个模板题,代码很短。 */ #include<iostream> #include<cstdio> #include<algorithm> #define maxn 500010 using namespace std; int tot,cnt,n,m,root[maxn]; int lc[maxn*20],rc[maxn*20],sum[maxn*20]; void build(int x,int &y,int l,int r,int v){ tot++;y=tot; sum[y]=sum[x]+1; if(l==r)return; int mid=(l+r)>>1; if(v<=mid){ rc[y]=rc[x]; build(lc[x],lc[y],l,mid,v); } else{ lc[y]=lc[x]; build(rc[x],rc[y],mid+1,r,v); } } int query(int x,int y){//两个时刻 int l=1,r=n,tmp=(y-x+1)/2; x=root[x-1];y=root[y]; while(l!=r){ if(sum[y]-sum[x]<=tmp)return 0; int mid=l+r>>1; if(sum[lc[y]]-sum[lc[x]]>tmp){ r=mid;x=lc[x];y=lc[y]; } else if(sum[rc[y]]-sum[rc[x]]>tmp){ l=mid+1;x=rc[x];y=rc[y]; } else return 0; } return l; } int main(){ scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=n;i++){ scanf("%d",&x); build(root[i-1],root[i],1,n,x); } for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); } }
/* 递归查询 注意不要把if(l==r)return l;写成 if(l==r){ if(sum[l]>k)return l; else return 0; } 因为l不是线段树下标,而是区间边界 */ #include<iostream> #include<cstdio> #include<algorithm> #define maxn 500010 using namespace std; int tot,cnt,n,m,root[maxn]; int lc[maxn*20],rc[maxn*20],sum[maxn*20]; void build(int x,int &y,int l,int r,int v){ tot++;y=tot; sum[y]=sum[x]+1; if(l==r)return; int mid=(l+r)>>1; if(v<=mid){ rc[y]=rc[x]; build(lc[x],lc[y],l,mid,v); } else{ lc[y]=lc[x]; build(rc[x],rc[y],mid+1,r,v); } } int query(int x,int y,int l,int r,int k){ if(l==r)return l; int mid=(l+r)>>1; int sz=sum[y]-sum[x]; if(sz<=k)return 0; if(sum[lc[y]]-sum[lc[x]]>k)return query(lc[x],lc[y],l,mid,k); if(sum[rc[y]]-sum[rc[x]]>k)return query(rc[x],rc[y],mid+1,r,k); return 0; } int main(){ freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=n;i++){ scanf("%d",&x); build(root[i-1],root[i],1,n,x); } for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); printf("%d\n",query(root[x-1],root[y],1,n,(y-x+1)/2)); } }