zoukankan      html  css  js  c++  java
  • BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

    BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N))

    -----------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    #define H(x) (lower_bound(H, H + n, x) - H + 1)
    #define lb(x) ((x) & -(x))
     
    const int maxn = 50009;
     
    int N, Q, Pos;
    int H[maxn], n;
     
    inline int getint() {
    char c = getchar();
    int ret = 0, f = 1;
    for(; !isdigit(c); c = getchar()) if(c == '-') f = 0;
    for(; isdigit(c); c = getchar()) ret = ret * 10 - '0' + c;
    return f ? ret : -ret;
    }
     
    struct O {
    int t, l, r, v;
    inline void Read() {
    t = getint(), l = getint(), r = getint(), v = getint();
    }
    } o[maxn];
     
    struct Node {
    Node *lc, *rc;
    int v;
    } pool[maxn * 400], *pt, *Null, *A[maxn], *B[maxn];
     
    void Init_sgt() {
    (pt = pool)->v = 0;
    pt->lc = pt->rc = pt;
    Null = pt++;
    }
     
    Node* Modify(Node* t, int l, int r, int ad) {
    Node* p = pt++;
    p->v = t->v + ad;
    if(l != r) {
    int m = (l + r) >> 1;
    if(Pos <= m) {
    p->lc = Modify(t->lc, l, m, ad);
    p->rc = t->rc;
    } else {
    p->lc = t->lc;
    p->rc = Modify(t->rc, m + 1, r, ad);
    }
    }
    return p;
    }
     
    Node *L0[20], *L1[20], *L[20];
    Node *R0[20], *R1[20];
     
    void Work() {
    Init_sgt();
    int ln, rn, sn;
    for(int i = 0; i <= N; i++) A[i] = B[i] = Null;
    for(int i = 0; i < Q; i++) if(o[i].t == 1) {
    Pos = H(o[i].v);
    for(int x = o[i].l; x <= N; x += lb(x)) {
    A[x] = Modify(A[x], 1, n, 1);
    B[x] = Modify(B[x], 1, n, o[i].l - 1);
    }
    for(int x = o[i].r + 1; x <= N; x += lb(x)) {
    A[x] = Modify(A[x], 1, n, -1);
    B[x] = Modify(B[x], 1, n, -o[i].r);
    }
    } else {
    ln = rn = sn = 0;
    for(int x = o[i].l; x; x -= lb(x)) L[sn++] = A[x];
    for(int x = o[i].l; x; x -= lb(x))
    L0[ln] = A[x], R1[ln++] = B[x];
    for(int x = o[i].r; x; x -= lb(x))
    R0[rn] = A[x], L1[rn++] = B[x];
    int l = 1, r = n, len = o[i].r - o[i].l + 1;
    while(l < r) {
    int m = (l + r) >> 1, cnt = 0;
    for(int x = 0; x < sn; x++) cnt += L[x]->rc->v * len;
    for(int x = 0; x < ln; x++)
    cnt += R1[x]->rc->v - o[i].r * L0[x]->rc->v;
    for(int x = 0; x < rn; x++)
    cnt += o[i].r * R0[x]->rc->v - L1[x]->rc->v;
    if(cnt >= o[i].v) {
    for(int x = 0; x < sn; x++) L[x] = L[x]->rc;
    for(int x = 0; x < ln; x++)
    R1[x] = R1[x]->rc, L0[x] = L0[x]->rc;
    for(int x = 0; x < rn; x++)
    R0[x] = R0[x]->rc, L1[x] = L1[x]->rc;
    l = m + 1;
    } else {
    o[i].v -= cnt;
    for(int x = 0; x < sn; x++) L[x] = L[x]->lc;
    for(int x = 0; x < ln; x++)
    R1[x] = R1[x]->lc, L0[x] = L0[x]->lc;
    for(int x = 0; x < rn; x++)
    R0[x] = R0[x]->lc, L1[x] = L1[x]->lc;
    r = m;
    }
    }
    printf("%d ", H[l - 1]);
    }
    }
     
    void Init() {
    N = getint(), Q = getint();
    n = 0;
    for(int i = 0; i < Q; i++) {
    o[i].Read();
    if(o[i].t == 1) H[n++] = o[i].v;
    }
    sort(H, H + n);
    n = unique(H, H + n) - H;
    }
     
    int main() {
    Init();
    Work();
    return 0;
    }

    -----------------------------------------------------------------------------------------

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2921  Solved: 1247
    [Submit][Status][Discuss]

    Description

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    Input

    第一行N,M
    接下来M行,每行形如1 a b c或2 a b c

    Output

    输出每个询问的结果

    Sample Input

    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3

    Sample Output

    1
    2
    1

    HINT



    【样例说明】

    第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

    的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

    1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

    大的数是 1 。‍


    N,M<=50000,N,M<=50000

    a<=b<=N

    1操作中abs(c)<=N

    2操作中abs(c)<=Maxlongint


    Source

  • 相关阅读:
    golang删除数组某个元素
    golang用通道实现信号量,控制并发个数
    什么是ScaleIO中的forwards rebuild和backwards rebuild?
    SQL Server中的database checkpoint
    如何将thick provision lazy zeroed的VMDK文件转换为thick provision eager zeroed?
    LoadTestAgentResultsLateException in VS2010
    SQL Server Instance无法启动了, 因为TempDB所在的分区没有了, 怎么办?
    VMware vCenter中, 如何辩认虚机上Raw Device Mapping过了的一块物理磁盘?
    SQL Server AlwaysOn Setup Step-By-Step Guide
    TPC-E在populate测试Database时需要注意的一些事项
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5161653.html
Copyright © 2011-2022 走看看