bzoj3524: [Poi2014]Couriers

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3524

题意:中文题。

分析:区间问题,并且询问的是大于区间一半的值,我们可以直接用可持久化线段树查询。O(nlogn+qlogn)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=500010;
const int MAX=100000000;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int siz,root[N],ls[20*N],rs[20*N],sum[20*N];
void updata(int l,int r,int x,int &y,int z) {
    y=++siz;sum[y]=sum[x]+1;
    if (l==r) return ;
    int mid=(l+r)>>1;
    ls[y]=ls[x];rs[y]=rs[x];
    if (z<=mid) updata(l,mid,ls[x],ls[y],z);
    else updata(mid+1,r,rs[x],rs[y],z);
}
int query(int l,int r,int x,int y,int z) {
    if (l==r) return l;
    int mid=(l+r)>>1;
    if (sum[ls[y]]-sum[ls[x]]>z) return query(l,mid,ls[x],ls[y],z);
    if (sum[rs[y]]-sum[rs[x]]>z) return query(mid+1,r,rs[x],rs[y],z);
    return 0;
}
int main()
{
    int i,n,m,x,y;
    scanf("%d%d", &n, &m);
    for (i=1;i<=n;i++) {
        scanf("%d", &x);
        updata(1,n,root[i-1],root[i],x);
    }
    while (m--) {
        scanf("%d%d", &x, &y);
        printf("%d\n", query(1,n,root[x-1],root[y],(y-x+1)/2));
    }
    return 0;
}


你可能感兴趣的:(bzoj3524: [Poi2014]Couriers)