• 【BZOJ3110】【Zjoi2013】K大数查询


    以后写数据结构还是要注意空间问题= =

    原题:

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
    如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    【样例说明】
    第一个操作 后位置 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

    有点奇怪的区间第k大,用煮席树好像没法做,选择权值线段树套区间线段树

    之前一直想不明白树套树怎么搞,主要问题在于修改外面的树的一个区间中的里面的树的一个区间,外面的树区间修改的标记似乎不好控制(因为同一个节点多次修改修改的里面的树的区间不一定一样)

    然后这道题因为是权值线段树和区间线段树套,权值线段树是单点修改,所以直接把权值线段树放到外层,然后暴力修改里面的区间线段树即可

    (外面的单点修改可以保留修改里面,但是外面如果区间修改就不行了,因为单点nlogn,区间最坏nlogn)

    然后空间问题,被迫把两个树分成两个数组写,然后里面push_down的时候调用成外面的

    然后debug了7h……

    最后发现依旧会MLE,只能把树里面存的left和right放到外面作为参数,mid在每个节点询问或修改的时候现场计算

    (其实大部分人都是这么写的,我只是不习惯= =)

    如果把left和right作为参数似乎就可以把里外两个树用一个数组了?

    以后还是要用把left和right做参数的写法= =

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 long long read(){long long z=0,mark=1;  char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
     9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    10     return z*mark;
    11 }
    12 int n,m;  int N;
    13 struct dcd{int sleft,sright,mid,root;}tree[1700000];
    14 struct ddc{int mid,lchild,rchild,delta;  long long svalue;}tree_2[21000000];
    15 //数字个数最坏5e4*5e4会爆int
    16 int tree_cnt=0;
    17 int new_node(int x){
    18     tree_2[x].lchild=tree_2[x].rchild=tree_2[x].svalue=tree_2[x].delta=0;
    19     return x;
    20 }
    21 void get_SegmentTree(int x,int _left,int _right){
    22     tree[x].sleft=_left,tree[x].sright=_right,tree[x].mid=(_left+_right)>>1;
    23     tree[x].root=new_node(++tree_cnt);
    24     if(_left!=_right){
    25         get_SegmentTree(x<<1,_left,tree[x].mid);
    26         get_SegmentTree(x<<1|1,tree[x].mid+1,_right);
    27     }
    28 }
    29 void push_down(int x,int uleft,int uright){
    30     int umid=(uleft+uright)>>1;
    31     if(!tree_2[x].lchild)  tree_2[x].lchild=new_node(++tree_cnt);
    32     if(!tree_2[x].rchild)  tree_2[x].rchild=new_node(++tree_cnt);
    33     //tree_2[tree_2[x].lchild].svalue+=(tree[x].mid-tree[x].sleft+1)*tree_2[x].delta;
    34     //tree_2[tree_2[x].rchild].svalue+=(tree[x].sright-tree[x].mid)*tree_2[x].delta;
    35     tree_2[tree_2[x].lchild].svalue+=(umid-uleft+1)*tree_2[x].delta;
    36     tree_2[tree_2[x].rchild].svalue+=(uright-umid)*tree_2[x].delta;
    37     tree_2[tree_2[x].lchild].delta+=tree_2[x].delta,tree_2[tree_2[x].rchild].delta+=tree_2[x].delta;
    38     tree_2[x].delta=0;
    39 }
    40 void modify_2(int x,int _left,int _right,int uleft,int uright){
    41     int umid=(uleft+uright)>>1;
    42     if(uleft==_left && uright==_right){
    43         tree_2[x].svalue+=uright-uleft+1,tree_2[x].delta++;
    44         return ;
    45     }
    46     push_down(x,uleft,uright);
    47     if(_left<=umid && _right>umid){
    48         modify_2(tree_2[x].lchild,_left,umid,uleft,umid);
    49         modify_2(tree_2[x].rchild,umid+1,_right,umid+1,uright);
    50     }
    51     else if(_right<=umid)  modify_2(tree_2[x].lchild,_left,_right,uleft,umid);
    52     else  modify_2(tree_2[x].rchild,_left,_right,umid+1,uright);
    53     tree_2[x].svalue=tree_2[tree_2[x].lchild].svalue+tree_2[tree_2[x].rchild].svalue;
    54     //这句忘了QAQ
    55     //if(tree_2[x].svalue<_value)  cout<<"fuck!!!"<<" "<<x<<endl;
    56 }
    57 void modify(int x,int y,int _left,int _right){
    58     modify_2(tree[x].root,_left,_right,1,n);
    59     if(tree[x].sleft==tree[x].sright)  return ;
    60     if(y<=tree[x].mid)  modify(x<<1,y,_left,_right);
    61     else  modify(x<<1|1,y,_left,_right);
    62 }
    63 long long query_2(int x,int _left,int _right,int uleft,int uright){
    64     int umid=(uleft+uright)>>1;
    65     if(uleft==_left && uright==_right)  return tree_2[x].svalue;
    66     push_down(x,uleft,uright);
    67     if(_left<=umid && _right>umid)
    68         return query_2(tree_2[x].lchild,_left,umid,uleft,umid)+query_2(tree_2[x].rchild,umid+1,_right,umid+1,uright);
    69     else if(_right<=umid)  return query_2(tree_2[x].lchild,_left,_right,uleft,umid);
    70     else  return query_2(tree_2[x].rchild,_left,_right,umid+1,uright);
    71 }
    72 int query(int x,long long y,int _left,int _right){
    73     if(tree[x].sleft==tree[x].sright)  return tree[x].sleft;
    74     long long rchild_cnt=query_2(tree[x<<1|1].root,_left,_right,1,n);
    75     if(y<=rchild_cnt)  query(x<<1|1,y,_left,_right);
    76     else  query(x<<1,y-rchild_cnt,_left,_right);
    77 }
    78 int main(){//freopen("ddd.in","r",stdin);
    79     cin>>n>>m;  N=n<<1;
    80     get_SegmentTree(1,0,N);
    81     int _mark,_left,_right;  long long _value;
    82     while(m --> 0){//趋向于
    83         _mark=read(),_left=read(),_right=read(),_value=read();
    84         if(_mark==1)  modify(1,_value+n,_left,_right);
    85         else  printf("%d
    ",query(1,_value,_left,_right)-n);
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    下载文件总结
    用PHP,怎么获取PHP.ini中的文件上传最大的字节数。也就是默认的2M
    TP框架下载功能 - 不想下天桥 - 博客园
    CSS,font-family,好看常用的中文字体
    安装Wamp后 Apache无法启动的解决方法
    :nth-child(n)
    list-style
    netbeans常用快捷键
    ideaic快捷键
    配置nutch
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6396071.html
Copyright © 2020-2023  润新知