• bzoj 3110[Zjoi2013]K大数查询


    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB

    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

    这种问题树套树什么的肯定是无脑刚啊可以用整体二分来做

    首先肯定要二分答案,验证 >= mid 的数的个数和 K 的大小关系 

    对于一个插入操作,如果他插入的数是比 mid 大的, 那么下一步二分的(l, mid) 的区间这个插入就不会产生贡献

    我们可以直接把他放入到 (mid + 1, r) 的区间中,反之同理

    如何查询 > mid 的个数呢

    用一个线段树维护区间 (l, r) 中> mid数的个数

    如果插入的数 > mid 就把他加入到线段树中

    查询的时候,如果 > mid 的个数 >= qk 

    说明第 qk 个数比mid大, 加入到(mid + 1, r)的区间中

    如果少,说明第K大的数在(l, mid) 的区间中, 把qk - > mid的个数

    放入到(l, mid)的区间中

    于是就完成了

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define LL long long
      6 
      7 using namespace std;
      8 
      9 const int MAXN = 5e4 + 10;
     10 const int MAXM = 5e4 + 10;
     11 
     12 int qq[MAXN];
     13 int temp[MAXM];
     14 LL ans[MAXN];
     15 
     16 struct query {
     17     int l, r;
     18     int c;
     19     int opr;    
     20 }  q[MAXN];
     21 
     22 struct segment {
     23     LL sum;
     24     int lazy;
     25     int clear;
     26     void init()
     27     {
     28         sum = 0;
     29         lazy = 0;
     30     }
     31 } seg[MAXN * 10];
     32 
     33 inline LL read()
     34 {
     35     LL x = 0, w = 1; char ch = 0;
     36     while(ch < '0' || ch > '9') {
     37         if(ch == '-') {
     38             w = -1;
     39         }
     40         ch = getchar();
     41     }
     42     while(ch >= '0' && ch <= '9') {
     43         x = x * 10 + ch - '0';
     44         ch = getchar();
     45     }
     46     return x * w;
     47 }
     48 
     49 int N, M;
     50 
     51 void pushdown(int k, LL l, LL r)
     52 {
     53     LL mid = (l + r) >> 1;
     54     if(seg[k].clear) {
     55         seg[k].clear = 0;
     56         seg[k << 1].init(), seg[k << 1 | 1].init();
     57         seg[k << 1].clear = seg[k << 1 | 1].clear = 1;
     58     }
     59     if(seg[k].lazy) {
     60         seg[k << 1].lazy += seg[k].lazy;
     61         seg[k << 1 | 1].lazy += seg[k].lazy;
     62         seg[k << 1].sum += (mid - l + 1) * seg[k].lazy;
     63         seg[k << 1 | 1].sum += (r - mid) * seg[k].lazy;
     64         seg[k].lazy = 0;
     65     }
     66 }
     67 
     68 void pushup(int k)
     69 {
     70     seg[k].sum = seg[k << 1].sum + seg[k << 1 | 1].sum;
     71 }
     72 
     73 LL query(int ql, int qr, int l, int r, int root)
     74 {
     75     //cout<<l<<" "<<r<<endl;
     76     if(ql <= l && qr >= r) {
     77         //cout<<ql<<" "<<qr<<" "<<l<<" "<<r<<" "<<seg[root].sum<<endl;
     78         return seg[root].sum;
     79     }
     80     int mid = (l + r) >> 1;
     81     pushdown(root, l, r);
     82     LL s = 0;
     83     //cout<<mid<<" "<<ql<<" "<<qr<<endl;
     84     if(ql <= mid) {
     85         s += query(ql, qr, l, mid, root << 1);
     86     } 
     87     //cout<<mid<<" "<<ql<<" "<<qr<<endl;
     88     if(qr > mid) {
     89         //cout<<mid<<" "<<ql<<" "<<qr<<endl;
     90         s += query(ql, qr, mid + 1, r, root << 1 | 1);
     91     }
     92     pushup(root);
     93     return s;
     94 }
     95 
     96 void add(int ul, int ur, int l, int r, int root)
     97 {
     98     if(ul <= l && ur >= r) {
     99         seg[root].sum += (r - l + 1);
    100         //cout<<ul<<" "<<ur<<" "<<l<<" "<<r<<" "<<seg[root].sum<<endl;
    101         seg[root].lazy++;
    102         return;
    103     }
    104     int mid = (l + r) >> 1;
    105     pushdown(root, l, r);
    106     if(ul <= mid) {
    107         add(ul, ur, l, mid, root << 1);
    108     }
    109     if(ur > mid) {
    110         add(ul, ur, mid + 1, r, root << 1 | 1);
    111     }
    112     pushup(root);
    113     return;
    114 }
    115 
    116 void solve(int l, int r, int a, int b)
    117 {
    118     /*cout<<l<<" "<<r<<" "<<a<<" "<<b<<endl;
    119     for(int i = l; i <= r; i++) {
    120         cout<<qq[i]<<" ";
    121     }
    122     cout<<endl<<endl;*/
    123     int mid = (a + b) >> 1;
    124     if(l > r) {
    125         return;
    126     }
    127     if(a == b) {
    128         for(int i = l; i <= r; i++) {
    129             int t = qq[i];
    130             if(q[t].opr == 2) {
    131                 ans[t] = mid;
    132             }
    133         }
    134         return;
    135     }
    136     int L = l, R = r;
    137     seg[1].init();
    138     seg[1].clear = 1;
    139     for(int i = l; i <= r; i++) {
    140         int t = qq[i];
    141         if(q[t].opr == 1) {
    142             if(q[t].c > mid) {
    143                 //cout<<q[t].l<<" "<<q[t].r<<endl;
    144                 add(q[t].l, q[t].r, 1, N, 1);
    145                 temp[R--] = t;    
    146             } else {
    147                 temp[L++] = t;
    148             }
    149         } else {
    150         //    cout<<q[t].l<<" "<<q[t].r<<endl;
    151             LL num = query(q[t].l, q[t].r, 1, N, 1);
    152         //    cout<<num<<endl;
    153             if(q[t].c > num) {
    154                 q[t].c -= num;
    155                 temp[L++] = t;
    156             } else {
    157                 temp[R--] = t;
    158             }
    159         }
    160     }
    161     //cout<<L<<" "<<R<<endl;
    162     for(int i = l; i < L; i++) {
    163         qq[i] = temp[i];
    164     }
    165     for(int i = r; i >= L; i--) {
    166         qq[i] = temp[++R];
    167     }
    168     solve(l, L - 1, a, mid);
    169     solve(L, r, mid + 1, b);
    170 }
    171 
    172 void open()
    173 {
    174     freopen("sequence1.in", "r", stdin);
    175     freopen("sequence.out", "w", stdout);
    176 }
    177 
    178 int main()
    179 {
    180     //open();
    181     N = read(), M = read();
    182     for(int i = 1; i <= M; i++) {
    183         q[i].opr = read();
    184         q[i].l = read(), q[i].r = read(), q[i].c = read();
    185         qq[i] = i;
    186     }
    187     solve(1, M, -N, N);
    188     for(int i = 1; i <= M; i++) {
    189         if(q[i].opr == 2) {
    190             printf("%lld
    ", ans[i]);
    191         }
    192     }
    193     return 0;
    194 }
    View Code
  • 相关阅读:
    【Express系列】第3篇——接入mysql
    【Express系列】第2篇——主程序的改造
    【Express系列】第1篇——项目创建
    AngularJS内置指令
    node服务端搭建学习笔记
    生成ssh key
    webstorm的常用操作
    VSCode 常用插件
    php集成包
    composer安装特别慢的解决方案
  • 原文地址:https://www.cnblogs.com/wuenze/p/8639460.html
Copyright © 2020-2023  润新知