【bzoj3110】[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

 



【样例说明】

第一个操作 后位置 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

 

一直不是很理解树套树是个什么鬼。
题解告诉我此题为线段树套线段树。一维维护权值,二维维护区间。
精髓还没有领悟到,果真我还是很弱QWQ
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cstring>
 6 #define ll long long 
 7 using namespace std;
 8 int a,b,c;
 9 int n,m,sz;
10 int root[200005];
11 int ls[20000005],rs[20000005],sum[20000005],lazy[20000005];
12 void pushdown(int k,int l,int r){
13     if ((!lazy[k])||l==r) return;//如果没标记或者已经到了底层
14     if (!ls[k])ls[k]=++sz;
15     if (!rs[k])rs[k]=++sz;
16     int mid=(l+r)>>1;
17     lazy[ls[k]]+=lazy[k];lazy[rs[k]]+=lazy[k];
18     sum[ls[k]]+=(mid-l+1)*lazy[k];
19     sum[rs[k]]+=(r-mid)*lazy[k];
20     lazy[k]=0;
21 }
22 
23 void modify(int &k,int l,int r,int a,int b){
24     if (!k)k=++sz;
25     pushdown(k,l,r);
26     if (a==l&&b==r){
27         lazy[k]++;
28         sum[k]+=(r-l+1);
29         return;
30     }
31     int mid=(l+r)>>1;
32     if (a>mid) modify(rs[k],mid+1,r,a,b);
33     else if (b<=mid) modify(ls[k],l,mid,a,b);
34     else modify(ls[k],l,mid,a,mid),modify(rs[k],mid+1,r,mid+1,b); 
35     sum[k]=sum[ls[k]]+sum[rs[k]];
36 }
37 
38 void insert(){
39     int l=1,r=n,k=1;
40     while (l!=r){
41         modify(root[k],1,n,a,b);
42         int mid=(l+r)>>1;
43         if (c>mid)l=mid+1,k=k<<1|1;
44         else r=mid,k=k<<1;
45     }
46     modify(root[k],1,n,a,b);
47 }
48 
49 int query(int k,int l,int r,int a,int b){
50     if (!k) return 0;
51     pushdown(k,l,r);
52     if (a==l&&b==r)return sum[k];
53     int mid=(l+r)>>1;
54     if (a>mid) return query(rs[k],mid+1,r,a,b);
55     else if (b<=mid) return query(ls[k],l,mid,a,b);
56     else return query(ls[k],l,mid,a,mid)+query(rs[k],mid+1,r,mid+1,b);
57 }
58 
59 int solve(){
60     int l=1,r=n,k=1;
61     while (l!=r){
62         int t=query(root[k<<1],1,n,a,b);
63         int mid=(l+r)>>1;
64         if (t>=c)r=mid,k=k<<1;
65         else l=mid+1,k=k<<1|1,c-=t;
66     }
67     return l;
68 }
69 
70 int main(){
71     freopen("sj.txt","r",stdin);
72     freopen("me.txt","w",stdout);
73     scanf("%d%d",&n,&m);
74     for (int i=1;i<=m;i++){
75         int f;
76         scanf("%d%d%d%d",&f,&a,&b,&c);
77         if (f==1)c=n-c+1,insert();
78         else printf("%d\n",n-solve()+1);
79     }
80 }

 

posted @ 2016-01-21 21:41  Alisahhh  阅读(188)  评论(0编辑  收藏  举报