zoukankan      html  css  js  c++  java
  • BZOJ 3110 【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

    N,M<=50000,N,M<=50000
    a<=b<=N

    1操作中abs(c)<=N

    2操作中c<=Maxlongint

      刚学了整体二分,跟随神犇的步伐走向了这道题......

      神犇:这道题不是整体二分裸题吗? 我:......

      也许是我真的太弱了吧:

      不过好歹是A了,讲一讲我的思路:

      首先,我们二分出一个答案$mid$,然后扫一遍当前区间内的询问,如果加入的数$x>=mid$,那么把这段区间的值都加$1$;这样就可以求出区间$>=mid$的数的个数了。

      如果你还不会可以支持区间修改、区间查询的树状数组,请左转树状数组区间修改加区间查询

      然后,根据这些东西判断一下当前询问该丢到左边还是右边,递归处理就可以了。还有不要忘了询问的是区间第$k$大,所以对于丢到左边的询问要先把贡献给算进去。

      这么做原理是什么呢?我觉得就是与普通的二分答案一样,只不过普通的二分答案只有一个询问,这里是把多个询问一起处理罢了。

      下面贴代码:

     1 #include<cstdio>
     2 #define maxn 50010
     3 
     4 using namespace std;
     5 typedef long long llg;
     6 
     7 struct data{
     8     int tp,l,r,k,id;
     9 }s[maxn],zl[maxn],zr[maxn];
    10 int n,m,ans[maxn],tt;
    11 llg c1[maxn],c2[maxn];
    12 
    13 int getint(){
    14     int w=0,q=0;
    15     char c=getchar();
    16     while((c<'0'||c>'9')&&c!='-') c=getchar();
    17     if(c=='-') q=1,c=getchar();
    18     while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    19     return q?-w:w;
    20 }
    21 
    22 void add(int x,int y){for(int i=x;i<=n;i+=i&(-i)) c1[i]+=y,c2[i]+=(llg)x*y;}
    23 llg sum(int x){
    24     llg ans(0);
    25     for(int i=x;i;i-=i&(-i)) ans+=(x+1)*c1[i]-c2[i];
    26     return ans;
    27 }
    28 
    29 void solve(int top,int end,int l,int r){
    30     if(l==r){
    31         for(int i=top;i<=end;i++)
    32             ans[s[i].id]=l;
    33         return;
    34     }
    35     int mid=l+r+1>>1,lo(0),ro(0);
    36     bool ll(0),rr(0);llg x;
    37     for(int i=top;i<=end;i++)
    38         if(s[i].tp==1)
    39             if(s[i].k>=mid) add(s[i].l,1),add(s[i].r+1,-1),zr[++ro]=s[i];
    40             else zl[++lo]=s[i];
    41         else{
    42             x=sum(s[i].r)-sum(s[i].l-1);
    43             if(x>=s[i].k) zr[++ro]=s[i],rr=1;
    44             else s[i].k-=x,zl[++lo]=s[i],ll=1;
    45         }
    46     for(int i=top;i<=end;i++)
    47         if(s[i].tp==1 && s[i].k>=mid) add(s[i].l,-1),add(s[i].r+1,1);
    48     for(int i=1;i<=lo;i++) s[top+i-1]=zl[i];
    49     for(int i=1;i<=ro;i++) s[top+i+lo-1]=zr[i];
    50     if(ll) solve(top,top+lo-1,l,mid-1);
    51     if(rr) solve(top+lo,end,mid,r);
    52 }
    53 
    54 int main(){
    55     n=getint();m=getint();
    56     for(int i=1;i<=m;i++){
    57         s[i].tp=getint();
    58         s[i].l=getint(); s[i].r=getint();
    59         s[i].k=getint();
    60         if(s[i].tp==2) s[i].id=++tt;
    61     }
    62     solve(1,m,1,n);
    63     for(int i=1;i<=tt;i++)
    64         printf("%d
    ",ans[i]);
    65     return 0;
    66 }
  • 相关阅读:
    Windows系统 Mysql5.6下载安装以及配置
    【翻译】Javascript “组件模式” 深入研究
    【原创】使用GridView实现绑定List并排序
    【翻译】【项目架构必备】Asp.Net MVC3 定义自己的项目模板
    【原创】也谈我如何解决Silverlight跨域访问安全性问题
    【翻译】MVC 3 Razor语法技巧之——The @helper syntax
    【翻译】Knockout 2.1版本发布&新特性一览
    【原创】三把利器快速制作代码帮助文档
    现代软件工程_团队项目_阿尔法阶段_第二次会议记录_2017.11.13
    现代软件工程_团队项目_阿尔法阶段_需求分析文档_2017.11.13
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5547552.html
Copyright © 2011-2022 走看看