《P3567 [POI2014]KUR-Couriers》

这题思考如何去查询。

我们可以建主席树。

那么对于区间的数量最多的数,我们可以“松弛“去查找。

当某个区间的数量大于一半时,我们就去找那个区间,然后到叶子节点,那么叶子节点的数量肯定就满足大于区间的一半。

显然这个数最多只能有一个,那么左右区间肯定只有一个被松弛到。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 5e5+5;
const int M = 1e5+5;
const LL Mod = 199999;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

int n,m,a[N],b[N],mp[N],rt[N*20],top = 0;
struct Node{int L,r;LL sum;}node[N*20];
int build(int L,int r)
{
    int idx = ++top;
    node[idx].sum = 0;
    if(L == r ) return idx;
    int mid = (L+r)>>1;
    node[idx].L = build(L,mid);
    node[idx].r = build(mid+1,r);
    return idx;
}
void Pushup(int idx)
{
    node[idx].sum = node[node[idx].L].sum + node[node[idx].r].sum;
}
int update(int x,int L,int r,int pos)
{
    int idx = ++top;
    node[idx] = node[x];
    if(L == r){node[idx].sum++;return idx;}
    int mid = (L+r)>>1;
    if(mid >= pos) node[idx].L = update(node[x].L,L,mid,pos);
    else node[idx].r = update(node[x].r,mid+1,r,pos);
    Pushup(idx);
    return idx;
}
int query(int lidx,int ridx,int L,int r,int dis)
{
    if(L == r)
    {
        int sum = node[ridx].sum-node[lidx].sum;
        if(sum <= dis) return 0;
        else return mp[L];
    }
    int mid = (L+r)>>1;
    int lsum = node[node[ridx].L].sum-node[node[lidx].L].sum;
    int rsum = node[node[ridx].r].sum-node[node[lidx].r].sum;
    if(lsum > dis) return query(node[lidx].L,node[ridx].L,L,mid,dis);
    if(rsum > dis) return query(node[lidx].r,node[ridx].r,mid+1,r,dis);
    return 0;
}
int main()
{
    n = read(),m = read();
    for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i];
    sort(a+1,a+n+1);
    int len = unique(a+1,a+n+1)-a-1;
    for(rg int i = 1;i <= n;++i)
    {
        int pos = lower_bound(a+1,a+len+1,b[i])-a;
        mp[pos] = b[i],b[i] = pos;
    }
    rt[0] = build(1,len);
    for(rg int i = 1;i <= n;++i) rt[i] = update(rt[i-1],1,len,b[i]);
    while(m--)
    {
        int L,r;L = read(),r = read();
        int ans = query(rt[L-1],rt[r],1,len,(r-L+1)/2);
        printf("%d\n",ans);
    }
    system("pause");
}
View Code

 

posted @ 2020-09-05 15:20  levill  阅读(140)  评论(0编辑  收藏  举报