【BZOJ】3524: [Poi2014]Couriers

【算法】主席树

【题解】例题,记录和,数字出现超过一半就递归查找。

主席树见【算法】数据结构

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
int read()
{
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
const int maxn=500010;
struct tree{int l,r,sum;}t[maxn*20];
int n,m,sz,root[maxn];

void insert(int L,int R,int x,int &y,int v){
    y=++sz;
    t[y]=t[x];t[y].sum++;
    if(L==R)return;
    int mid=(L+R)>>1;
    if(v<=mid)insert(L,mid,t[x].l,t[y].l,v);
    else insert(mid+1,R,t[x].r,t[y].r,v);
}
int ask(int L,int R,int x,int y,int v){
    if(L==R)return L;
    else{
        int mid=(L+R)>>1;
        if(v<t[t[y].l].sum-t[t[x].l].sum)return ask(L,mid,t[x].l,t[y].l,v);else
        if(v<t[t[y].r].sum-t[t[x].r].sum)return ask(mid+1,R,t[x].r,t[y].r,v);else
        return 0;
    }
}
int main(){
    scanf("%d%d",&n,&m);
    int u;
    for(int i=1;i<=n;i++){
        u=read();
        insert(1,n,root[i-1],root[i],u);
    }
    int v;
    for(int i=1;i<=m;i++){
        u=read();v=read();
        printf("%d\n",ask(1,n,root[u-1],root[v],(v-u+1)>>1));
    }
    return 0;
}
View Code

 

posted @ 2017-08-17 21:46  ONION_CYC  阅读(232)  评论(0编辑  收藏  举报