[BZOJ3110][Zjoi2013]K大数查询 树套树

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3110

我们建一棵权值线段树,并对里面的节点建普通区间线段树,注意动态开点。对于查询就用类似于二分的操作就好了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef unsigned int uint;
 6 int inline readint(){
 7     int Num=0,Flag=1;char ch;
 8     while((ch=getchar())<'0'||ch>'9') if(ch=='-') break;
 9     if(ch=='-') Flag=-1; else Num=ch-'0';
10     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
11     return Num*Flag;
12 }
13 void outint(int x){
14     if(x>=10) outint(x/10);
15     putchar(x%10+'0');
16 }
17 int n,m,opt,a,b,c;
18 int rt[(50000<<2)+10],lc[20000000],rc[20000000],col[20000000],cnt=0;
19 uint sum[20000000];
20 void inline Pushup(int &x){
21     sum[x]=sum[lc[x]]+sum[rc[x]];
22 }
23 void inline Pushdown(int &x,int l,int r){
24     if(!col[x]||l==r) return;
25     if(!lc[x]) lc[x]=++cnt;
26     if(!rc[x]) rc[x]=++cnt;
27     col[lc[x]]+=col[x];
28     col[rc[x]]+=col[x];
29     uint mid=l+r>>1;
30     sum[lc[x]]+=(mid-l+1)*col[x];
31     sum[rc[x]]+=(r-mid)*col[x];
32     col[x]=0;
33 }
34 void Modify(int &x,int l,int r,int L,int R){
35     if(!x) x=++cnt;
36     if(L<=l&&r<=R){
37         col[x]++;
38         sum[x]+=r-l+1;
39         return;
40     }
41     Pushdown(x,l,r);
42     int mid=l+r>>1;
43     if(L<=mid) Modify(lc[x],l,mid,L,R);
44     if(R>mid) Modify(rc[x],mid+1,r,L,R);
45     Pushup(x);
46 }
47 uint Qry(int &x,int l,int r,int L,int R){
48     if(L<=l&&r<=R) return sum[x];
49     Pushdown(x,l,r);
50     int mid=l+r>>1;
51     uint s=0;
52     if(L<=mid) s=Qry(lc[x],l,mid,L,R);
53     if(R>mid) s+=Qry(rc[x],mid+1,r,L,R);
54     return s;
55 }
56 void Insert(){
57     int x=1,l=1,r=n;
58     while(l!=r){
59         int mid=l+r>>1;
60         Modify(rt[x],1,n,a,b);
61         if(c<=mid) r=mid,x<<=1;
62         else l=mid+1,x=x<<1|1;
63     }
64     Modify(rt[x],1,n,a,b);
65 }
66 void Solve(){
67     int x=1,l=1,r=n;
68     while(l!=r){
69         int mid=l+r>>1;
70         uint rk=Qry(rt[x<<1|1],1,n,a,b);
71         if(rk>=c) l=mid+1,x=x<<1|1;
72         else r=mid,x<<=1,c-=rk;
73     }
74     outint(l);
75     putchar('\n');
76 }
77 int main(){
78     n=readint();
79     m=readint();
80     for(int i=1;i<=m;i++){
81         opt=readint();
82         a=readint();
83         b=readint();
84         c=readint();
85         if(opt==1) Insert();
86         else Solve();
87     }
88     return 0;
89 }

 

posted @ 2017-09-19 20:40  halfrot  阅读(177)  评论(0编辑  收藏  举报