• [主席树]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
    ",L);
        }
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    js中剩余参数
    css中 @mixin的使用
    前端Vue中常用rules校验规则
    vue 运行时报错: Cannot assign to read only property 'exports' of object 'Object'
    webpack 常用的loader
    二维码图片合成 ----合成图片以便微信长按保存(移动端)
    VUE中引入第三方JS
    小程序开发者工具--快捷键
    小程序注意事项
    webpack+ES6+less 开发环境搭建
  • 原文地址:https://www.cnblogs.com/mastervan/p/11166648.html
Copyright © 2020-2023  润新知