Couriers bzoj-3524 Poi-2014
题目大意:给定n个数的序列,询问区间内是否存在一个在区间内至少出现了(区间长度>>1)次的数。如果有,输出该数,反之输出0。
注释:$1\le n,m\le 5\cdot 10^5$。
想法:主席树裸题。
主流做法就是弄一个Existence数组询问有没有这样的数,然后查询区间中位数即可。
但是可以在query的时候强行查询,因为没有输出0,直接输出即可。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define N 500010 using namespace std; int cnt[N<<5],ls[N<<5],rs[N<<5],tot; int a[N],b[N],root[N]; int build(int l,int r) { int pos=++tot,mid=(l+r)>>1; if(l==r) return pos; ls[pos]=build(l,mid); rs[pos]=build(mid+1,r); return pos; } int update(int pre,int l,int r,int k) { int pos=++tot,mid=(l+r)>>1; cnt[pos]=cnt[pre]+1; ls[pos]=ls[pre]; rs[pos]=rs[pre]; if(l==r) return pos; if(k<=mid) ls[pos]=update(ls[pre],l,mid,k); else rs[pos]=update(rs[pre],mid+1,r,k); return pos; } // bool Existence(int x,int y,int l,int r,int Want) // { // if(l==r) return (cnt[y]-cnt[x])>=Want; // int mid=(l+r)>>1; // int LR=1; // if(cnt[ls[y]]-cnt[ls[x]]>cnt[rs[y]]-cnt[rs[x]]) LR=0; // else if(cnt[ls[y]]-cnt[ls[x]]<cnt[rs[y]]-cnt[rs[x]]) LR=2; // if(LR==0) return Existence(ls[x],ls[y],l,mid,Want); // if(LR==2) return Existence(rs[x],rs[y],mid+1,r,Want); // return Existence(ls[x],ls[y],l,mid,Want)|Existence(rs[x],rs[y],mid+1,r,Want); // } // int query(int x,int y,int l,int r,int k) // { // int mid=(l+r)>>1; // if(l==r) return b[l]; // int dlt=cnt[ls[y]]-cnt[ls[x]]; // if(dlt>=k) return query(ls[x],ls[y],l,mid,k); // else return query(rs[x],rs[y],mid+1,r,k-dlt); // } int query(int x,int y,int l,int r,int k) { int mid=(l+r)>>1; if(l==r) return l; int L=cnt[ls[y]]-cnt[ls[x]],R=cnt[rs[y]]-cnt[rs[x]]; if(L>k) return query(ls[x],ls[y],l,mid,k); if(R>k) return query(rs[x],rs[y],mid+1,r,k); else return 0; } int main() { int n,m; cin >> n >> m ; for(int i=1;i<=n;i++) scanf("%d",&a[i])/* ,b[i]=a[i] */; sort(b+1,b+n+1); /* int len=unique(b+1,b+n+1)-b-1; */ root[0]=build(1,n); for(int i=1;i<=n;i++) { // int t=lower_bound(b+1,b+n+1,a[i])-b; root[i]=update(root[i-1],1,n,a[i]); } for(int x,y,i=1;i<=m;i++) { scanf("%d%d",&x,&y); // if(Existence(root[x-1],root[y],1,n,(y-x+1)/2+1)) printf("%d\n",query(root[x-1],root[y],1,n,(y-x+1)/2+1)); // else printf("0\n"); printf("%d\n",query(root[x-1],root[y],1,n,(y-x+1)>>1)); } return 0; }
小结:主席树真强... ...
原文地址:https://www.cnblogs.com/ShuraK/p/9383690.html
时间: 2024-10-24 16:29:03