bzoj 3524: [Poi2014]Couriers 可持久化线段树

来源:互联网 发布:js如何控制文字漂浮 编辑:程序博客网 时间:2024/04/27 17:31

题意

给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
n,m≤500000

分析

有时候刷刷水题其实蛮好的。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=500005;int n,m,sz,a[N],root[N];struct tree{int l,r,s;}t[N*30];int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}void ins(int &d,int p,int l,int r,int x){    d=++sz;    t[d]=t[p];t[d].s++;    if (l==r) return;    int mid=(l+r)/2;    if (x<=mid) ins(t[d].l,t[p].l,l,mid,x);    else ins(t[d].r,t[p].r,mid+1,r,x);}int query(int d,int p,int l,int r,int x){    if (l==r) return t[d].s-t[p].s>x?l:0;    int mid=(l+r)/2;    if (t[t[d].l].s-t[t[p].l].s>t[t[d].r].s-t[t[p].r].s) return query(t[d].l,t[p].l,l,mid,x);    else return query(t[d].r,t[p].r,mid+1,r,x);}int main(){    n=read();m=read();    int mx=0;    for (int i=1;i<=n;i++) a[i]=read(),mx=max(mx,a[i]);    for (int i=1;i<=n;i++) ins(root[i],root[i-1],1,mx,a[i]);    while (m--)    {        int l=read(),r=read();        printf("%d\n",query(root[r],root[l-1],1,mx,(r-l+1)/2));    }    return 0;}
0 0