bzoj3524 Couriers

题目大意:给出一段区间,求所求区间中出现次数超过区间长一半的数,若没有则输出0。

主席树的题吖……

可以说很裸了。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 500050
int n,m,mx,a[N];
struct ND
{
    int x,id;
}nd[N];
bool cmp(ND a,ND b)
{
    return a.x<b.x;
}
int to[N],rt[N],tot;
struct segtree
{
    int ls,rs,v;
}tr[30*N];
void update(int u)
{
    tr[u].v = tr[tr[u].ls].v+tr[tr[u].rs].v;
}
void insert(int l,int r,int &u,int k,int qx)
{
    u=++tot;
    tr[u]=tr[k];
    if(l==r)
    {
        tr[u].v++;
        return ;
    }
    int mid = (l+r)>>1;
    if(qx<=mid)insert(l,mid,tr[u].ls,tr[k].ls,qx);
    else insert(mid+1,r,tr[u].rs,tr[u].rs,qx);
    update(u);
}
int query(int l,int r,int a,int b,int x)
{
    if(l==r)return l;
    int mid = (l+r)>>1;
    if(2*(tr[tr[b].ls].v-tr[tr[a].ls].v)>x)return query(l,mid,tr[a].ls,tr[b].ls,x);
    else if(2*(tr[tr[b].rs].v-tr[tr[a].rs].v)>x)return query(mid+1,r,tr[a].rs,tr[b].rs,x);
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&nd[i].x);
        nd[i].id=i;
    }
    sort(nd+1,nd+1+n,cmp);
    int las = -1;
    for(int i=1;i<=n;i++)
    {
        if(las!=nd[i].x)
        {
            las=nd[i].x;
            to[++mx] = nd[i].x;
        }
        a[nd[i].id]=mx;
    }
    for(int i=1;i<=n;i++)
    {
        insert(1,mx,rt[i],rt[i-1],a[i]);
    }
    for(int l,r,i=1;i<=m;i++)
    {
        scanf("%d%d",&l,&r);
        int ans = query(1,mx,rt[l-1],rt[r],r-l+1);
        ans =  to[ans];
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9582017.html