HDU6278(主席树+二分)

题意

区间第k大

代码

#include<cstdio>
#include<algorithm>
#include<string.h>
#include <string.h>
#include <math.h>
#include <vector>
using namespace std;

typedef long long ll;
const int N = 1e5+5;
int n, m, cnt, root[N], a[N], l, r, k;
struct Node {
    int l, r;
    int sum;
}T[N*40];
vector<int>v;
int getid(int x)
{
    return lower_bound(v.begin(), v.end(), x)-v.begin()+1;
}
void update(int l, int r, int &cur, int pre, int pos)
{
    T[++cnt] = T[pre];
    T[cnt].sum++;
    cur = cnt;
    if(l == r) return;
    int mid = (l+r)>>1;
    if(mid>=pos) update(l, mid, T[cur].l, T[pre].l, pos);
    else update(mid+1, r, T[cur].r, T[pre].r, pos);
}
int query(int l ,int r ,int x, int y, int k)
{
    if(l == r) return l;
    int mid = (l+r)>>1;
    int sum = T[T[y].l].sum - T[T[x].l].sum;
    if(sum>=k) return query(l, mid, T[x].l, T[y].l, k);
    else return query(mid+1, r, T[x].r, T[y].r, k-sum);
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        root[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            update(1, n, root[i], root[i-1], getid(a[i]));
        }
        for(int i = 1; i <= m; i++)
        {
            int R, L;
            scanf("%d%d", &L, &R);
            r = R-L+1;
            l = 1;
            int ans = 1;
            while(l<=r)
            {
                int mid=(l+r)/2;
                int q=query(1,n,root[L-1],root[R], R-L+2-mid);
                if(v[q-1]>=mid)
                {
                    ans=max(mid,ans);
                    l=mid+1;
                }
                else
                    r=mid-1;

            }
            printf("%d\n",ans);
        }
        v.clear();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/QiHang_QiHang/article/details/81263202
今日推荐