[主席树]JZOJ 3379 查询

Description

对于一个整数序列,查询区间第k大数可以在O(logN)的时间内轻松完成。现在我们对这个问题进行推广。



考虑带重复数的集合(multiset)。定义在该类集合上的并操作“+”为两个集合的所有数不剔除重复得到的结果。比如,若A={1,2,2,3},B={2,3,4,4},则C={1,2,2,2,3,3,4,4}。



对于一个给定序列A[1..N],定义A[x..y]为包含y-x+1个元素的集合{A[x],A[x+1],…,A[y]}。现在,给定整数序列A,你需要回答很多询问,其中第i个询问要求集合A[x[i,1]..y[i,1]]+A[x[i,2]..y[i,2]]+…+A[x[i,ki]..y[i,ki]]中第pi小的元素。
 

Input

输入的第一行包含两个整数N和M,分别表示整数序列的长度和询问的个数。

第二行N个整数给出整数序列A。

第3到第M+2行给出了所有的询问。第i+2行前两个整数为ki和pi,接下来2ki个整数给出x[i, 1], y[i, 1], x[i,2], …, x[i, ki], y[i, ki]。这些数按照题目中的定义描述了第i个询问。

Output

对于每一个询问,输出相应的结果,即从小到大排序后的第pi个元素。
 

Sample Input

8 3
1 2 3 1 2 3 1 2
2 4 1 4 3 7
2 4 1 3 6 8
5 31 1 8 1 8 1 8 1 8 1 8

Sample Output

1
2
3
 

Data Constraint

【数据规模】

第1、2个测试数据满足N ≤ 1 000,M ≤ 1 000。

第3、4个测试数据满足ki = 1。

所有的测试点满足N ≤ 200 000,M ≤ 200 000,0 ≤ A[i] ≤ 1 000 000,ki ≤ 5。

保证1 ≤ x[i, j] ≤ N,1 ≤ y[i, j] ≤ N,1 ≤ pi ≤ ∑j(y[i, j] - x[i, j] + 1)。
 

Hint

【样例说明】

第一个询问集合为{1,2,3,1,3,1,2,3,1},第4小元素为1。

分析

离散化都不用的水题

把所有区间端点放进去一起跳瞎搞一通就行了

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <memory.h>
using namespace std;
const int N=2e5+10;
const int Max=1e6;
struct Seg {
    int v,l,r;
}t[40*N];
int n,m,rt[N],cnt,l[N],r[N];

void Insert(int &x,int l,int r,int k) {
    t[++cnt]=t[x];x=cnt;t[x].v++;
    if (l==r) return;
    int mid=l+r>>1;
    if (k<=mid) Insert(t[x].l,l,mid,k);
    else Insert(t[x].r,mid+1,r,k);
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1,a;i<=n;i++) scanf("%d",&a),rt[i]=rt[i-1],Insert(rt[i],0,Max,a);
    for (int i=1;i<=m;i++) {
        int k,p;
        scanf("%d%d",&k,&p);
        for (int i=1;i<=k;i++) scanf("%d%d",&l[i],&r[i]),l[i]=rt[l[i]-1],r[i]=rt[r[i]];
        int L=0,R=Max,mid;
        while (L<R) {
            int rk=0;mid=L+R>>1;
            for (int i=1;i<=k;i++) rk+=t[t[r[i]].l].v-t[t[l[i]].l].v;
            if (p<=rk) {
                for (int i=1;i<=k;i++) l[i]=t[l[i]].l,r[i]=t[r[i]].l;
                R=mid;
            }
            else {
                for (int i=1;i<=k;i++) l[i]=t[l[i]].r,r[i]=t[r[i]].r;
                L=mid+1;p-=rk;
            }
        }
        printf("%d\n",L);
    }
}
View Code

 

posted @ 2019-07-10 21:29  Vagari  阅读(186)  评论(0编辑  收藏  举报