• 【ZJOI2013】k大数查询 BZOJ 3110


    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

    思路:

    都是从浙江挂下来的考数据结构的歪风邪气←_←
    一看就知道是数据结构题啦=。=
    树套树。。我是写的树状数组套线段树。
    外层的树状数组记录有关数字的信息,内层的线段树记录有关位置的信息。
    也就是说我在[5,8]中加入了3这个数,就在外层的树状数组add_bit(3),然后在树状数组对应的节点上把[5,8]这个节点打上+1的标记。
    每次对于一个询问[L,R]中第k大的数,我们先转化为求第k小,然后二分答案,寻找在[l,r]中有多少比Mid小的数,收缩上下界就行了。
    p.s 网上说开树套树空间会爆,所以内层线段树要动态开点,我不知道要不要。。反正我是动态的。。不过跟静态的应该区别还是挺大的。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <string>
      4 #include <cstdio>
      5 #include <cstdlib>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <queue>
      9 #include <stack>
     10 #include <map>
     11 #include <set>
     12 #include <list>
     13 #include <vector>
     14 #include <ctime>
     15 #include <functional>
     16 #define pritnf printf
     17 #define scafn scanf
     18 #define For(i,j,k) for(int i=(j);i<=(k);(i)++)
     19 #define Clear(a) memset(a,0,sizeof(a))
     20 using namespace std;
     21 typedef long long LL;
     22 typedef unsigned int Uint;
     23 const int INF=0x3fffffff;
     24 //==============struct declaration==============
     25 struct Node{
     26      Node *lc,*rc;
     27      long long sum,add;
     28      Node(){lc=rc=NULL;sum=add=0;}
     29 };
     30 //==============var declaration=================
     31 const int MAXN=80050;
     32 int n,m,L,R;
     33 long long sum[MAXN*2],addv[MAXN*2];
     34 Node *BitTree[MAXN];
     35 //==============function declaration============
     36 int lowbit(int x){return x&-x;}
     37 void add_bit(int x);
     38 void add_seg(Node *&o,int l,int r);
     39 long long  query_bit(int x);
     40 long long query_seg(Node *&i,int l,int r,long long add);
     41 void update(Node *&o,int l,int r);
     42 void add_num(int o,int l,int r);
     43 long long query_num(int o,int l,int r,long long add);
     44 //==============main code=======================
     45 int main()
     46 {
     47 #define FILE__
     48 #ifdef FILE__
     49     freopen("input","r",stdin);
     50     freopen("output","w",stdout);
     51 #endif
     52     scanf("%d%d",&n,&m);n++;
     53     for(int i=1;i<=n;i++) BitTree[i]=NULL;
     54     while (m--){
     55         int cmd,a,b;long long c;scanf("%d%d%d%lld",&cmd,&a,&b,&c);
     56         if (cmd==1){
     57              L=a;R=b;
     58              add_bit(c);add_num(1,1,n-1);
     59         }
     60         else if (cmd==2){
     61             int low=1,high=n-1,mid;
     62             L=a;R=b;
     63             long long Num_Exist=query_num(1,1,n-1,0);
     64             c=Num_Exist-c+1;
     65             while (low<high){
     66                 mid=(low+high)>>1;
     67                 long long tmp=query_bit(mid);
     68                 if (tmp<c)     low=mid+1;
     69                 if (tmp>=c)     high=mid;
     70             }
     71             printf("%d
    ",low);
     72         }
     73     }
     74    return 0;
     75 }
     76 //================fuction code====================
     77 void add_bit(int x){
     78    while (x<=n){
     79        add_seg(BitTree[x],1,n-1);
     80        x+=lowbit(x);
     81    }
     82 }
     83 void add_seg(Node *&o,int l,int r){
     84     int m=(l+r)>>1;
     85     if (o==NULL)  o=new(Node);
     86     if (L<=l&&r<=R){
     87         o->add++;
     88         update(o,l,r);
     89         return;
     90     }
     91     if (m>=L)   add_seg(o->lc,l,m);
     92     if (m<R)    add_seg(o->rc,m+1,r);
     93     update(o,l,r);
     94 }
     95 void update(Node *&o,int l,int r){
     96     o->sum=0;
     97     if (o->lc!=NULL)    o->sum+=o->lc->sum;
     98     if (o->rc!=NULL)    o->sum+=o->rc->sum;
     99     o->sum+=(r-l+1)*o->add;
    100 }
    101 long long query_bit(int x){
    102     long long res=0;
    103     while (x>0){
    104         res+=query_seg(BitTree[x],1,n-1,0);
    105         x-=lowbit(x);
    106     }
    107     return res;
    108 }
    109 long long query_seg(Node *&o,int l,int r,long long add){
    110     if (o==NULL)    return add*(min(r,R)-max(l,L)+1);
    111     int m=(l+r)>>1;
    112     if (L<=l&&r<=R)
    113         return o->sum+(r-l+1)*add;
    114     long long Left=0,Right=0;
    115     if (m>=L)    Left=query_seg(o->lc,l,m,add+o->add);
    116     if (m<R)    Right=query_seg(o->rc,m+1,r,add+o->add);
    117     return Left+Right;
    118 }
    119 void add_num(int o,int l,int r){
    120     if (L<=l&&r<=R){
    121         addv[o]++;
    122         sum[o]+=r-l+1;
    123     }
    124     else{
    125         int lc=o*2,rc=o*2+1,m=(l+r)>>1;
    126         if (m>=L)    add_num(lc,l,m);
    127         if (m<R)    add_num(rc,m+1,r);
    128         sum[o]=sum[lc]+sum[rc]+addv[o]*(r-l+1);
    129     }
    130 }
    131 long long query_num(int o,int l,int r,long long add){
    132     int lc=o*2,rc=o*2+1,m=(l+r)>>1;
    133     if (L<=l&&r<=R)
    134         return sum[o]+add*(r-l+1);
    135     long long Left=0,Right=0;
    136     if (m>=L)  Left=query_num(lc,l,m,add+addv[o]);
    137     if (m<R)  Right=query_num(rc,m+1,r,add+addv[o]);
    138     return Left+Right;
    139 }
    Prob_3110
    
    

       

    
    
    
    
  • 相关阅读:
    Teamviewer12完美破解版去除时间限制完美使用
    winFrom程序更新自动安装
    sql 根据指定字符截取前面几个字符
    下拉框带搜索
    easyui 展开缩起
    p1001 谁拿了最多的奖学金
    p1217 乒乓球
    p1911 珠心算问题
    p1848 记数问题
    入坑archlinux
  • 原文地址:https://www.cnblogs.com/Houjikan/p/4302662.html
Copyright © 2020-2023  润新知