BZOJ 3110 [Zjoi2013]K大数查询(整体二分)
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 11654 Solved: 3505
[Submit][Status][Discuss]
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
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
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操作中c<=Maxlongint
题解
求第K大。
然后我们把权值设为n-c+1;
最后答案为n-ans+1就把问题转化为了第k小
不过这题是插入。其实不是很难毕竟只是把权值小于mid的数的位置都加一就行了,我们把修改二分和一个位置多少个权值没有关系。
和以前唯一的区别就是这次是整体修改,用线段树就行了(就是慢)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const long long N=100010; 8 struct query{ 9 long long type,x,y,w,id; 10 }q[N],c2[N],c1[N]; 11 long long ans[N],m,n,tot; 12 struct tree{ 13 long long l,r,lazy,sum; 14 }tr[N*5]; 15 void update(long long now){ 16 tr[now].sum=tr[now*2].sum+tr[now*2+1].sum; 17 } 18 void pushdown(long long now){ 19 if(tr[now].lazy==0)return; 20 tr[now*2].sum+=(tr[now*2].r-tr[now*2].l+1)*tr[now].lazy; 21 tr[now*2+1].sum+=(tr[now*2+1].r-tr[now*2+1].l+1)*tr[now].lazy; 22 tr[now*2].lazy+=tr[now].lazy; 23 tr[now*2+1].lazy+=tr[now].lazy; 24 tr[now].lazy=0; 25 } 26 void build(long long l,long long r,long long now){ 27 tr[now].l=l;tr[now].r=r; 28 if(l==r)return; 29 long long mid=(l+r)>>1; 30 build(l,mid,now*2); 31 build(mid+1,r,now*2+1); 32 } 33 void add(long long l,long long r,long long c,long long now){ 34 pushdown(now); 35 if(tr[now].l==l&&tr[now].r==r){ 36 tr[now].sum+=(tr[now].r-tr[now].l+1)*c; 37 tr[now].lazy+=c; 38 return; 39 } 40 long long mid=(tr[now].l+tr[now].r)>>1; 41 if(l>mid)add(l,r,c,now*2+1); 42 else if(r<=mid)add(l,r,c,now*2); 43 else{ 44 add(l,mid,c,now*2); 45 add(mid+1,r,c,now*2+1); 46 } 47 update(now); 48 } 49 long long check(long long l,long long r,long long now){ 50 pushdown(now); 51 if(tr[now].l==l&&tr[now].r==r){ 52 return tr[now].sum; 53 } 54 long long mid=(tr[now].l+tr[now].r)>>1; 55 if(l>mid)return check(l,r,now*2+1); 56 else if(r<=mid)return check(l,r,now*2); 57 else return check(l,mid,now*2)+check(mid+1,r,now*2+1); 58 } 59 void solve(long long l,long long r,long long L,long long R){ 60 if(l>r)return ; 61 if(L==R){ 62 for(long long i=l;i<=r;i++){ 63 if(q[i].type==2)ans[q[i].id]=L; 64 } 65 return; 66 } 67 long long mid=(L+R)>>1; 68 long long lnow=0;long long rnow=0; 69 for(long long i=l;i<=r;i++){ 70 if(q[i].type==1){ 71 if(q[i].w<=mid){ 72 add(q[i].x,q[i].y,1,1); 73 c1[++lnow]=q[i]; 74 } 75 else c2[++rnow]=q[i]; 76 } 77 else{ 78 long long tmp=check(q[i].x,q[i].y,1); 79 if(tmp>=q[i].w)c1[++lnow]=q[i]; 80 else{ 81 q[i].w-=tmp; 82 c2[++rnow]=q[i]; 83 } 84 } 85 } 86 for(long long i=1;i<=lnow;i++){ 87 if(c1[i].type==1)add(c1[i].x,c1[i].y,-1,1); 88 } 89 for(long long i=1;i<=lnow;i++){ 90 q[l+i-1]=c1[i]; 91 } 92 for(long long i=1;i<=rnow;i++){ 93 q[l+lnow+i-1]=c2[i]; 94 } 95 solve(l,l+lnow-1,L,mid); 96 solve(l+lnow,r,mid+1,R); 97 } 98 int main(){ 99 scanf("%lld%lld",&n,&m); 100 build(1,n,1); 101 for(long long i=1;i<=m;i++){ 102 long long k,a,b,c; 103 scanf("%lld%lld%lld%lld",&k,&a,&b,&c); 104 if(k==1){ 105 q[i].type=1;q[i].x=a;q[i].y=b;q[i].w=n-c+1; 106 } 107 else{ 108 q[i].type=2;q[i].x=a;q[i].y=b;q[i].w=c;q[i].id=++tot; 109 } 110 } 111 solve(1,m,-n,n); 112 for(long long i=1;i<=tot;i++){ 113 printf("%lld\n",n-ans[i]+1); 114 } 115 return 0; 116 }