zoukankan      html  css  js  c++  java
  • BZOJ 3110: [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2276  Solved: 1021

    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

    解题:整体二分+树状数组改段求段

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 200010;
     4 struct QU {
     5     int x,y,k,id,cache;
     6 } Q[maxn],A[maxn],B[maxn];
     7 int c[2][maxn],ans[maxn];
     8 void add(int *c,int i,int val) {
     9     while(i < maxn) {
    10         c[i] += val;
    11         i += i&-i;
    12     }
    13 }
    14 int sum(int *c,int i,int ret = 0) {
    15     while(i > 0) {
    16         ret += c[i];
    17         i -= i&-i;
    18     }
    19     return ret;
    20 }
    21 void solve(int lt,int rt,int L,int R) {
    22     if(lt > rt) return;
    23     if(L == R) {
    24         for(int i = lt; i <= rt; ++i)
    25             if(Q[i].id > -1) ans[Q[i].id] = L;
    26         return;
    27     }
    28     int mid = (L + R)>>1,a = 0,b = 0;
    29     for(int i = lt; i <= rt; ++i) {
    30         if(Q[i].id == -1) {
    31             if(Q[i].k > mid) {
    32                 add(c[0],Q[i].x,1);
    33                 add(c[0],Q[i].y+1,-1);
    34                 add(c[1],Q[i].x,Q[i].x);
    35                 add(c[1],Q[i].y+1,-Q[i].y-1);
    36                 A[a++] = Q[i];
    37             }else B[b++] = Q[i];
    38         } else {
    39             int tmp = (Q[i].y+1)*sum(c[0],Q[i].y) - sum(c[1],Q[i].y)
    40                     - (Q[i].x)*sum(c[0],Q[i].x-1) + sum(c[1],Q[i].x-1);
    41             if(tmp + Q[i].cache >= Q[i].k) A[a++] = Q[i];
    42             else {
    43                 Q[i].cache += tmp;
    44                 B[b++] = Q[i];
    45             }
    46         }
    47     }
    48     for(int i = lt; i <= rt; ++i) {
    49         if(Q[i].id == -1 && Q[i].k > mid) {
    50             add(c[0],Q[i].x,-1);
    51             add(c[0],Q[i].y+1,1);
    52             add(c[1],Q[i].x,-Q[i].x);
    53             add(c[1],Q[i].y+1,Q[i].y+1);
    54         }
    55     }
    56     for(int i = 0; i < b; ++i) Q[lt + i] = B[i];
    57     for(int i = 0; i < a; ++i) Q[lt + b + i] = A[i];
    58     solve(lt,lt+b-1,L,mid);
    59     solve(lt+b,rt,mid+1,R);
    60 }
    61 int main() {
    62     int n,m,op,ask = 0;
    63     scanf("%d%d",&n,&m);
    64     for(int i = 0; i < m; ++i) {
    65         scanf("%d%d%d%d",&op,&Q[i].x,&Q[i].y,&Q[i].k);
    66         if(op == 2) Q[i].id = ask++;
    67         else Q[i].id = -1;
    68         Q[i].cache = 0;
    69     }
    70     solve(0,m-1,-n,n);
    71     for(int i = 0; i < ask; ++i) printf("%d
    ",ans[i]);
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    grep
    virtualbox共享文件夹无法创建软链接的解决方法
    openH264的双向链表实现
    openH264构建过程
    Ninja构建系统入门
    ubuntu上安装meson & 如何使用meson编译C代码
    ln: failed to create symbolic link ‘libopenh264.so.6’: Operation not permitted
    RAII-资源获取即初始化
    可变参数实现原理-参数栈
    一个统计多文件单行字符串出现次数QT实现
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4784629.html
Copyright © 2011-2022 走看看