zoukankan      html  css  js  c++  java
  • [luoguP2617] Dynamic Ranking(树状数组 套 主席树 + 离散化)

    传送门

    BZOJ上是权限题,洛谷赞啊。

    求区间 K 大数很简单。

    但是如果修改某个数的话,那么就得把这个数及后面所建的主席树都更新一遍 nlogn,显然不行。

    所以可以在外面套一个树状数组来优化,树状数组的每一个节点都表示某个区间的主席树。

    所以可以通过树状数组来求前缀和主席树。

    具体实现看代码。

    ——代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 
     5 const int MAXN = 20005;
     6 int n, m, tot, cnt, size, t1, t2;
     7 int a[MAXN], b[MAXN], x[MAXN], y[MAXN], z[MAXN], q1[MAXN], q2[MAXN], root[MAXN], ls[MAXN * 100], rs[MAXN * 100], sum[MAXN * 100];
     8 char s[MAXN];
     9 
    10 inline int read()
    11 {
    12     int x = 0;
    13     char ch = getchar();
    14     for(; !isdigit(ch); ch = getchar());
    15     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    16     return x;
    17 }
    18 
    19 inline void insert(int &now, int l, int r, int x, int v)
    20 {
    21     if(!now) now = ++cnt;
    22     sum[now] += v;
    23     if(l == r) return;
    24     int mid = (l + r) >> 1;
    25     if(x <= mid) insert(ls[now], l, mid, x, v);
    26     else insert(rs[now], mid + 1, r, x, v);
    27 }
    28 
    29 inline int query(int l, int r, int x)
    30 {
    31     if(l == r) return l;
    32     int i, mid = (l + r) >> 1, ans = 0;
    33     for(i = 1; i <= t1; i++) ans -= sum[ls[q1[i]]];
    34     for(i = 1; i <= t2; i++) ans += sum[ls[q2[i]]];
    35     if(x <= ans)
    36     {
    37         for(i = 1; i <= t1; i++) q1[i] = ls[q1[i]];
    38         for(i = 1; i <= t2; i++) q2[i] = ls[q2[i]];
    39         return query(l, mid, x);
    40     }
    41     else
    42     {
    43         for(i = 1; i <= t1; i++) q1[i] = rs[q1[i]];
    44         for(i = 1; i <= t2; i++) q2[i] = rs[q2[i]];
    45         return query(mid + 1, r, x - ans);
    46     }
    47 }
    48 
    49 int main()
    50 {
    51     int i, j, l, r;
    52     n = read();
    53     m = read();
    54     for(i = 1; i <= n; i++) a[i] = read(), b[++tot] = a[i];
    55     for(i = 1; i <= m; i++)
    56     {
    57         for(s[i] = getchar(); s[i] != 'Q' && s[i] != 'C'; s[i] = getchar());
    58         if(s[i] == 'C') x[i] = read(), z[i] = read(), b[++tot] = z[i];
    59         else x[i] = read(), y[i] = read(), z[i] = read();
    60     }
    61     
    62     std::sort(b + 1, b + tot + 1);
    63     size = std::unique(b + 1, b + tot + 1) - (b + 1);
    64     for(i = 1; i <= n; i++) a[i] = std::lower_bound(b + 1, b + size + 1, a[i]) - b;
    65     for(i = 1; i <= m; i++)
    66         if(s[i] == 'C')
    67             z[i] = std::lower_bound(b + 1, b + size + 1, z[i]) - b;
    68     
    69     for(i = 1; i <= n; i++)
    70         for(j = i; j <= size; j += j & -j)
    71             insert(root[j], 1, size, a[i], 1);
    72     
    73     for(i = 1; i <= m; i++)
    74         if(s[i] == 'Q')
    75         {
    76             t1 = t2 = 0;
    77             for(j = x[i] - 1; j; j -= j & -j) q1[++t1] = root[j];
    78             for(j = y[i]; j; j -= j & -j) q2[++t2] = root[j];
    79             printf("%d
    ", b[query(1, size, z[i])]);
    80         }
    81         else 
    82         {
    83             for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, a[x[i]], -1);
    84             a[x[i]] = z[i];
    85             for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, z[i], 1);
    86         }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    CodeSmith中SchemaExplorer类详解
    配置 TransactSQL 调试器
    获取SQL所有数据库名、所有表名、所有字段名、表字段长度
    SQL SERVER数据类型与C#数据类型对照表
    C# orm linq 真的不错
    游戏外挂教程
    RDLC钻取式报表开发
    脚本整理
    访问Exchange Mail
    本人开发的带提示的TextBox控件
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6878964.html
Copyright © 2011-2022 走看看