• [BZOJ3110] [Zjoi2013] K大数查询 (树套树)


    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操作中c<=Maxlongint

    Source

    Solution

      树套树。。。说难不难,说简单不简单。曾经花了一星期理解内外线段树的关系。。。一直不理解怎么“套”一棵树的

      树套树的一般做法是用两个树形结构,外层代表区间,内层代表该区间下的权值信息或其它的什么

      相当于一个二维矩阵,一维是区间信息一维是权值信息。

      嘛,其实就是外层线段树纪录它对应的内层线段树的节点编号,内层线段树纪录该区间下与某权值范围的的结点信息

      为了省空间,需用动态开点的姿势。在这里给各位提个醒:这道题开2000000就好。

      嗯= =其实就是把线段树update和query写两遍233

      蛋碎了一地。数组开大MLE,数组开小RE。

      这道题外层区间内层权值有点麻烦,所以换一种思路:外层权值线段树内层区间线段树。递归查询某一段权值范围内有多少数,若个数小于询问数则向左子树递归,否则向右子树递归。

      = =

      好吧我的确给别人讲不懂 _(:з」∠)_

      代码常熟大地飞起。标记永久化是什么可以吃吗

      yky大爷讲了一种奥妙丛丛的压缩空间的方法:把结构体里的变量压缩为x位整型。因为好像存和要用unsigned int于是干脆用long long。具体用法看代码。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 struct seg1
      5 {
      6     ll l:28, r:28, sum:36, lazy:36;
      7 }p1[20000005];
      8 struct operation
      9 {
     10     ll op, l, r, val;
     11 }op[50005];
     12 ll n, p2[150005], ptot, cd[50005], ctot, ql, qr, val;
     13   
     14 void push_up(ll o, ll l, ll r)
     15 {
     16     p1[o].sum = p1[p1[o].l].sum + p1[p1[o].r].sum + p1[o].lazy * (r - l + 1);
     17 }
     18   
     19 void push_down(ll o, ll l, ll r)
     20 {
     21     ll mid = (l + r) >> 1;
     22     if(!p1[o].l) p1[o].l = ++ptot;
     23     if(!p1[o].r) p1[o].r = ++ptot;
     24     if(p1[o].lazy)
     25     {
     26         p1[p1[o].l].lazy += p1[o].lazy;
     27         p1[p1[o].r].lazy += p1[o].lazy;
     28         p1[p1[o].l].sum += p1[o].lazy * (mid - l + 1);
     29         p1[p1[o].r].sum += p1[o].lazy * (r - mid);
     30         p1[o].lazy = 0;
     31     }
     32 }
     33   
     34 void update1(ll o, ll l, ll r)
     35 {
     36     ll mid = (l + r) >> 1;
     37     if(ql <= l && r <= qr)
     38     {
     39         p1[o].sum += r - l + 1, p1[o].lazy++;
     40         return;
     41     }
     42     push_down(o, l, r);
     43     if(ql <= mid) update1(p1[o].l, l, mid);
     44     if(mid < qr) update1(p1[o].r, mid + 1, r);
     45     push_up(o, l, r);
     46 }
     47   
     48 void update2(ll o, ll l, ll r)
     49 {
     50     ll mid = (l + r) >> 1;
     51     if(!p2[o]) p2[o] = ++ptot;
     52     update1(p2[o], 1, n);
     53     if(l == r) return;
     54     if(val <= mid) update2(o << 1, l, mid);
     55     else update2(o << 1 | 1, mid + 1, r);
     56 }
     57   
     58 ll query1(ll o, ll l, ll r)
     59 {
     60     ll mid = (l + r) >> 1, cnt = 0;
     61     if(ql <= l && r <= qr) return p1[o].sum;
     62     push_down(o, l, r);
     63     if(ql <= mid) cnt = query1(p1[o].l, l, mid);
     64     if(mid < qr) cnt += query1(p1[o].r, mid + 1, r);
     65     return cnt;
     66 }
     67   
     68 ll query2(ll o, ll l, ll r, ll rk)
     69 {
     70     ll mid = (l + r) >> 1;
     71     if(l == r) return l;
     72     if(!p2[o]) p2[o] = ++ptot;
     73     val = query1(p2[o << 1 | 1], 1, n);
     74     if(val < rk) return query2(o << 1, l, mid, rk - val);
     75     return query2(o << 1 | 1, mid + 1, r, rk);
     76 }
     77   
     78 int main()
     79 {
     80     ll m;
     81     scanf("%lld%lld", &n, &m);
     82     for(ll i = 1; i <= m; i++)
     83     {
     84         scanf("%lld%lld%lld%lld", &op[i].op, &op[i].l, &op[i].r, &op[i].val);
     85         if(op[i].op == 1) cd[++ctot] = op[i].val;
     86     }
     87     sort(cd + 1, cd + ctot + 1);
     88     for(int i = 1; i <= m; i++)
     89         if(op[i].op == 1)
     90             op[i].val = lower_bound(cd + 1, cd + ctot + 1, op[i].val) - cd;
     91     for(ll i = 1; i <= m; i++)
     92         if(op[i].op == 1)
     93         {
     94             ql = op[i].l, qr = op[i].r, val = op[i].val;
     95             update2(1, 1, ctot);
     96         }
     97         else
     98         {
     99             ql = op[i].l, qr = op[i].r;
    100             printf("%lld
    ", cd[query2(1, 1, ctot, op[i].val)]);
    101         }
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    Scala与Mongodb实践1-----mongodbCRUD
    Scala实践14
    Scala实践13
    Scala实践12
    Scala实践11
    Scala实践10
    Scala实践9
    Scala实践6
    Scala实践8
    Oracle Object Type
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5414921.html
Copyright © 2020-2023  润新知