BZOJ3524: [Poi2014]Couriers

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3524

可持久化线段树。连离散化都不用。找一个出现次数最大的数那就比较是左儿子大还是右儿子大找下去就可以了。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 500500
#define ll long long
using namespace std;
int sum[maxn*20],ls[maxn*20],rs[maxn*20];
int root[maxn],a[maxn];
int ss,cnt,n,m,k,cnt2;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void add(int l,int r,int x,int &y,int val){
    y=++cnt;
    sum[y]=sum[x]+1;
    if (l==r) return ;
    ls[y]=ls[x]; rs[y]=rs[x];
    int mid=(l+r)/2;
    if (val<=mid) add(l,mid,ls[x],ls[y],val);
    else add(mid+1,r,rs[x],rs[y],val);
}
void jud(int x,int y){
    int l=1,r=n;
    int a=root[y],b=root[x-1];
    while (l<r){
        int mid=(l+r)/2;
        if (sum[ls[a]]-sum[ls[b]]>sum[rs[a]]-sum[rs[b]]) {r=mid; a=ls[a]; b=ls[b];}
        else {l=mid+1; a=rs[a]; b=rs[b];}    
    }
    if (sum[a]-sum[b]>(y-x+1)/2) printf("%d\n",l);
    else puts("0");
}
int main(){
    n=read(); m=read();
    rep(i,1,n) a[i]=read();
    rep(i,1,n) add(1,n,root[i-1],root[i],a[i]);
    rep(i,1,m){
        int x=read(),y=read();
        jud(x,y);
    }
    return 0;
}

 

posted on 2015-12-21 20:15  ctlchild  阅读(1987)  评论(0编辑  收藏  举报

导航