首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【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\n",query(1,_value,_left,_right)-n);
86     }
87     return 0;
88 }
View Code

 

posted on 2017-02-14 07:30  cdcq_old  阅读(190)  评论(0编辑  收藏  举报