zoukankan      html  css  js  c++  java
  • bzoj3110: [Zjoi2013]K大数查询 【cdq分治&树套树】

      模板题,折腾了许久。

      cqd分治整体二分,感觉像是把询问分到答案上。

      1 #include <bits/stdc++.h>
      2 #define rep(i, a, b) for (int i = a; i <= b; i++)
      3 #define drep(i, a, b) for (int i = a; i >= b; i--)
      4 #define REP(i, a, b) for (int i = a; i < b; i++)
      5 #define pb push_back
      6 #define mp make_pair
      7 #define clr(x) memset(x, 0, sizeof(x))
      8 #define xx first
      9 #define yy second
     10 using namespace std;
     11 typedef long long i64;
     12 typedef pair<int, int> pii;
     13 const int inf = ~0U >> 1;
     14 const i64 INF = ~0ULL >> 1;
     15 template <typename T> void Max(T &a, T &b) { if (a < b) a = b; }
     16 template <typename T> void Min(T &a, T &b) { if (a > b) a = b; }
     17 //******************************************
     18  
     19 const int maxn = 50005;
     20  
     21 struct Seg_Tree {
     22     int sum[maxn << 3], lazy[maxn << 3];
     23     void Push_down(int o, int m) {
     24         if (!lazy[o]) return;
     25         lazy[o << 1] += lazy[o], lazy[o << 1 | 1] += lazy[o];
     26         sum[o << 1] += lazy[o] * (m - (m >> 1)), sum[o << 1 | 1] += lazy[o] * (m >> 1);
     27         lazy[o] = 0;
     28     }
     29     void Push_up(int o) { sum[o] = sum[o << 1] + sum[o << 1 | 1]; }
     30     void update(int o, int l, int r, int ql, int qr, int v) {
     31         if (ql <= l && r <= qr) {
     32             lazy[o] += v;
     33             sum[o] += v * (r - l + 1);
     34             return;
     35         }
     36         Push_down(o, r - l + 1);
     37         int mid = l + r >> 1;
     38         if (ql <= mid) update(o << 1, l, mid, ql, qr, v);
     39         if (qr > mid) update(o << 1 | 1, mid + 1, r, ql, qr, v);
     40         Push_up(o);
     41     }
     42     int query(int o, int l, int r, int ql, int qr) {
     43         if (ql <= l && r <= qr) return sum[o];
     44         Push_down(o, r - l + 1);
     45         int mid = l + r >> 1;
     46         int ret(0);
     47         if (ql <= mid) ret += query(o << 1, l, mid, ql, qr);
     48         if (qr > mid) ret += query(o << 1 | 1, mid + 1, r, ql, qr);
     49         return ret;
     50     }
     51     void CLR() { clr(sum), clr(lazy); }
     52 } T;
     53  
     54 struct Complex {
     55     int flag, x, y, c, id;
     56     inline bool operator < (const Complex &A) const {
     57         return id < A.id;
     58     }
     59 } src[maxn];
     60  
     61 int N, ans[maxn], v[maxn];
     62 void cdq(int ansl, int ansr, int l, int r) {
     63     if (ansl == ansr) {
     64         rep(i, l, r) if (src[i].flag == 2) ans[src[i].id] = ansl;
     65         return;
     66     }
     67     if (l > r) return;
     68     sort(src + l, src + r + 1);
     69     int m = ansl + ansr + 1 >> 1;
     70     int j = l;
     71     rep(i, l, r) {
     72         if (src[i].flag == 1) {
     73             if (src[i].c >= m) T.update(1, 1, N, src[i].x, src[i].y, 1), v[i] = 1;
     74             else v[i] = 0;
     75         }
     76         else {
     77             int t = T.query(1, 1, N, src[i].x, src[i].y);
     78             if (t >= src[i].c) v[i] = 1;
     79             else src[i].c -= t, v[i] = 0;
     80         }
     81         j += !v[i];
     82     }
     83     rep(i, l, r)
     84         if (src[i].flag == 1)
     85             if (src[i].c >= m) T.update(1, 1, N, src[i].x, src[i].y, -1);
     86     int t = j - 1;
     87     if (j != l)
     88     rep(i, l, t) {
     89         while (j < r && v[j]) ++j;
     90         if (v[i]) swap(src[i], src[j]), swap(v[i], v[j]), ++j;
     91     }
     92     cdq(ansl, m - 1, l, t);
     93     cdq(m, ansr, t + 1, r);
     94 }
     95  
     96 int read() {
     97     int l = 1, s = 0; char ch = getchar();
     98     while (ch < '0' || ch > '9') { if (ch == '-') l = -1; ch = getchar(); }
     99     while (ch >= '0' && ch <= '9') { s = (s << 1) + (s << 3) + ch - '0'; ch = getchar(); }
    100     return s * l;
    101 }
    102 int main() {
    103     int n, m; scanf("%d%d", &n, &m);
    104     rep(i, 1, m) scanf("%d%d%d%d", &src[i].flag, &src[i].x, &src[i].y, &src[i].c), src[i].id = i;
    105     N = n;
    106     cdq(-n, n, 1, m);
    107     sort(src + 1, src + 1 + m);
    108     rep(i, 1, m) if (src[i].flag == 2) printf("%d
    ", ans[i]);
    109     return 0;
    110 }
    View Code

      树套树本来想把代表区间的那个线段树开在外面,不是不可以,但是lazy标记可能要一个vector才能存,因为我要存多个种类。

      然后就只能把代表数字那一维开在外面,代表这一段数字在1-n这个区间的分布情况,这样就可以在第二层线段树上打lazy标记。

     1 #include <bits/stdc++.h>
     2 #define rep(i, a, b) for (register int i = a; i <= b; i++)
     3 #define drep(i, a, b) for (register int i = a; i >= b; i--)
     4 #define REP(i, a, b) for (register int i = a; i < b; i++)
     5 #define pb push_back
     6 #define mp make_pair
     7 #define clr(x) memset(x, 0, sizeof(x))
     8 #define xx first
     9 #define yy second
    10 using namespace std;
    11 typedef long long i64;
    12 typedef pair<int, int> pii;
    13 const int inf = ~0U >> 1;
    14 const i64 INF = ~0ULL >> 1;
    15 //*******************************
    16  
    17 const int maxn = 200005, maxnn = 20000005;
    18  
    19 int root[maxn << 2];
    20 int ls[maxnn], rs[maxnn], sum[maxnn], lazy[maxnn];
    21  
    22 int ndtot, n, N;
    23 inline void Push_up(int o) { sum[o] = sum[ls[o]] + sum[rs[o]]; }
    24 inline void Push_down(int o, int m) {
    25     if (!lazy[o]) return;
    26     if (!ls[o]) ls[o] = ++ndtot;
    27     if (!rs[o]) rs[o] = ++ndtot;
    28     lazy[ls[o]] += lazy[o], lazy[rs[o]] += lazy[o];
    29     sum[ls[o]] += lazy[o] * (m - (m >> 1)), sum[rs[o]] += lazy[o] * (m >> 1);
    30     lazy[o] = 0;
    31 }
    32 void update(int &k, int l, int r, int ql, int qr, int v) {
    33     if (!k) k = ++ndtot;
    34     if (ql <= l && r <= qr) {
    35         sum[k] += v * (r - l + 1);
    36         lazy[k] += v;
    37         return;
    38     }
    39     int mid = l + r >> 1;
    40     Push_down(k, r - l + 1);
    41     if (ql <= mid) update(ls[k], l, mid, ql, qr, v);
    42     if (qr > mid) update(rs[k], mid + 1, r, ql, qr, v);
    43     Push_up(k);
    44 }
    45 void insrt(int o, int l, int r, int ql, int qr, int c) {
    46     while (l != r) {
    47         int mid = l + r >> 1;
    48         update(root[o], 1, n, ql, qr, 1);
    49         if (c <= mid) o <<= 1, r = mid;
    50         else o = o << 1 | 1, l = mid + 1;
    51     }
    52     update(root[o], 1, n, ql, qr, 1);
    53 }
    54  
    55 int query(int o, int l, int r, int ql, int qr) {
    56     if (!o) return 0;
    57     if (ql <= l && r <= qr) return sum[o];
    58     Push_down(o, r - l + 1);
    59     int mid = l + r >> 1;
    60     int ret(0);
    61     if (ql <= mid) ret += query(ls[o], l, mid, ql, qr);
    62     if (qr > mid) ret += query(rs[o], mid + 1, r, ql, qr);
    63     return ret;
    64 }
    65 int solve(int o, int l, int r, int ql, int qr, int c) {
    66     while (l != r) {
    67         int mid = l + r >> 1;
    68         int t = query(root[o << 1 | 1], 1, n, ql, qr);
    69         if (t >= c) l = mid + 1, o = o << 1 |1;
    70         else r = mid, o = o << 1, c -= t;
    71     }
    72     return l;
    73 }
    74  
    75 int main() {
    76     int m; scanf("%d%d", &n, &m);
    77     N = 2 * n + 1;
    78     while (m--) {
    79         int flag, a, b, c; scanf("%d%d%d%d", &flag, &a, &b, &c);
    80         if (flag == 1) {
    81             c += n + 1;
    82             insrt(1, 1, N, a, b, c);
    83         }
    84         else printf("%d
    ", solve(1, 1, N, a, b, c) - n - 1);
    85     }
    86 }
    View Code
  • 相关阅读:
    C# 读写 ini 配置文件
    [转]VB 读写ini 配置文件
    js实现隔行变色-------Day40
    Camel Games借助AWS在爆发式增长中提供优质游戏体验
    深入浅出--UNIX多进程编程之fork()函数
    【玩转微信公众平台之八】 演示样例代码分析
    jQuery 选择具有特殊属性的元素
    下载超星或读秀图书时,怎么搞定完整书签?
    意外的php之学习笔记
    POJ 1182 (经典食物链 /并查集扩展)
  • 原文地址:https://www.cnblogs.com/y7070/p/5069546.html
Copyright © 2011-2022 走看看