网上几乎清一色树套树,但是我就写个整体二分吧(其实是我不会树套树……)
这题还是和原来步骤一样,二分-判定-划分,当二分答案为m的时候
询问:大于等于m的个数大于等于k那就可能追求更大,划到右边;
不满足意味着答案要更小,那些大于等于m的修改操作对询问影响不变,k减去他们贡献的个数,划到左边
修改:显然大于等于m的划到右边,小于m划到左边
两个部分内都是操作都是按时间线的顺序的
注意这里的修改是——区间修改,区间查询……不好要上线段树?
突然想起来树状数组也是可以解决区间求改区间查询的
首先我们知道,区间修改时要维护一个差分数组d[i],代表[i..n]都加上d[i]
区间修改就是对d[l]+,d[r+1]-,然后每个位置的修改总和就等于d[]的前缀和 这就是单点查询
区间查询怎么办?我们还是想方设法变成前缀和,我们知道[l,r]=sum(r)-sum(l-1)
而sum[x]这个前缀和又怎么求呢?我们知道sum[x]=sumpre[x](初始和)+sumdelta[x](增量和)
重点是增量和,结合刚才的区间修改d[],我们发现,sumdelta[x]=∑d[i]*(x-i+1)=(x+1)*∑d[i]-∑d[i]*i
然后显然我们维护两个树状数组d[i]和d[i]*i即可
这题就解决了,没有tle,zjoi良心了一把……
UPD:这题啊现在在bzoj上非常坑,因为加强了数据……
转c++练模板的时候发现的,为什么不弄个hack……害得我以为c++有什么特殊之处呢……
坑点是50000*50000爆了树状数组统计时的int,换成unsigned int就好……
上面那个pascal程序我也顺便改了%%%(pascal范围检测比c++严格……)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 7 using namespace std; 8 struct node{int op,l,r,k,p;} a[50010],b[50010]; 9 int q[50010],g[50010][2],c[50010],d[50010],ans[50010]; 10 bool can[50010],v[50010]; 11 int n,m,t,tot,p; 12 13 int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 17 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 void work(int x,int w,int f) 21 { 22 for (int i=x; i<=n; i+=i&-i) 23 { 24 if (!v[i]) {v[i]=1; q[++tot]=i;} 25 g[i][f]+=w; 26 } 27 } 28 29 int ask(int x,int f) 30 { 31 int s=0; 32 for (int i=x;i; i-=i&-i) s+=g[i][f]; 33 return s; 34 } 35 36 unsigned int sum(int x) //注意啊注意啊…… 37 { 38 return (x+1)*ask(x,0)-ask(x,1); 39 } 40 41 void cdq(int l,int r,int f,int t) 42 { 43 if (l>r||f>t) return; 44 int m=(l+r)>>1,h; tot=h=0; 45 for (int i=f; i<=t; i++) 46 if (a[i].op==1&&a[i].k>=d[m]) 47 { 48 work(a[i].l,1,0); 49 work(a[i].r+1,-1,0); 50 work(a[i].l,a[i].l,1); 51 work(a[i].r+1,-a[i].r-1,1); 52 can[i]=1; ++h; 53 } 54 else if (a[i].op==2) 55 { 56 unsigned int s=sum(a[i].r)-sum(a[i].l-1); 57 if (s>=a[i].k) 58 { 59 ans[a[i].p]=m; 60 can[i]=1; ++h; 61 } 62 else a[i].k-=s; 63 } 64 65 for (int i=1; i<=tot; i++) 66 { 67 int x=q[i]; v[x]=0; 68 g[x][0]=g[x][1]=0; 69 } 70 int f1=f,f2=t-h+1; 71 for (int i=f; i<=t; i++) 72 if (can[i]) 73 { 74 b[f2++]=a[i]; 75 can[i]=0; 76 } 77 else b[f1++]=a[i]; 78 for (int i=f; i<=t; i++) 79 a[i]=b[i]; 80 cdq(l,m-1,f,f1-1); 81 cdq(m+1,r,f1,t); 82 } 83 84 int main() 85 { 86 n=read(); m=read(); 87 for (int i=1;i<=m; i++) 88 { 89 a[i].op=read(); a[i].l=read(); a[i].r=read(); a[i].k=read(); 90 a[i].p=i; 91 if (a[i].op==1) c[++t]=a[i].k; 92 } 93 sort(c+1,c+t+1); 94 p=1; d[1]=c[1]; 95 for (int i=2;i<=t; i++) 96 if (c[i]!=c[i-1]) d[++p]=c[i]; 97 98 cdq(1,p,1,m); 99 for (int i=1;i<=m;i++) 100 if (ans[i]) printf("%d\n",d[ans[i]]); 101 return 0; 102 }
1 type node=record 2 l,r,k,op,p:longint; 3 end; 4 5 var a,b:array[0..50010] of node; 6 q,ans,c,g,d:array[0..50010] of longint; 7 v1,v2:array[0..50010] of boolean; 8 i,t,n,m,tot,p:longint; 9 10 procedure swap(var a,b:longint); 11 var c:longint; 12 begin 13 c:=a; 14 a:=b; 15 b:=c; 16 end; 17 18 procedure sort(l,r:longint); 19 var i,j,x:longint; 20 begin 21 i:=l; 22 j:=r; 23 x:=c[(l+r) shr 1]; 24 repeat 25 while c[i]<x do inc(i); 26 while x<c[j] do dec(j); 27 if not(i>j) then 28 begin 29 swap(c[i],c[j]); 30 inc(i); 31 dec(j); 32 end; 33 until i>j; 34 if l<j then sort(l,j); 35 if i<r then sort(i,r); 36 end; 37 38 function lowbit(x:longint):longint; 39 begin 40 exit(x and (-x)); 41 end; 42 43 procedure addc(x,w:longint); 44 begin 45 while x<=n do 46 begin 47 if not v2[x] then 48 begin 49 v2[x]:=true; 50 inc(tot); 51 q[tot]:=x; 52 end; 53 inc(c[x],w); 54 x:=x+lowbit(x); 55 end; 56 end; 57 58 procedure addg(x,w:longint); 59 begin 60 while x<=n do 61 begin 62 inc(g[x],w); 63 x:=x+lowbit(x); 64 end; 65 end; 66 67 function askc(x:longint):longint; 68 begin 69 askc:=0; 70 while x>0 do 71 begin 72 askc:=askc+c[x]; 73 x:=x-lowbit(x); 74 end; 75 end; 76 77 function askg(x:longint):longint; 78 begin 79 askg:=0; 80 while x>0 do 81 begin 82 askg:=askg+g[x]; 83 x:=x-lowbit(x); 84 end; 85 end; 86 87 function sum(x:longint):longword; 88 begin 89 exit(longword(askg(x))*longword(x+1)-askc(x)); //pascal范围检测严格…… 90 end; 91 92 procedure cdq(l,r,f,t:longint); 93 var m,h,l1,l2:longint; 94 s:longword; 95 begin 96 if (f>t) or (l>r) then exit; 97 m:=(l+r) shr 1; 98 h:=0; tot:=0; 99 for i:=f to t do 100 if (a[i].op=1) and (a[i].k>=d[m]) then 101 begin 102 addg(a[i].l,1); 103 addg(a[i].r+1,-1); 104 addc(a[i].l,a[i].l); 105 addc(a[i].r+1,-a[i].r-1); 106 v1[i]:=true; inc(h); 107 end 108 else if (a[i].op=2) then 109 begin 110 s:=sum(a[i].r)-sum(a[i].l-1); 111 if s>=a[i].k then 112 begin 113 ans[a[i].p]:=m; 114 v1[i]:=true; inc(h); 115 end 116 else a[i].k:=a[i].k-s; 117 end; 118 119 for i:=1 to tot do 120 begin 121 c[q[i]]:=0; 122 g[q[i]]:=0; 123 v2[q[i]]:=false; 124 end; 125 l1:=f; l2:=t-h+1; 126 for i:=f to t do 127 if v1[i] then 128 begin 129 b[l2]:=a[i]; 130 inc(l2); 131 v1[i]:=false; 132 end 133 else begin 134 b[l1]:=a[i]; 135 inc(l1); 136 end; 137 138 for i:=f to t do 139 a[i]:=b[i]; 140 141 cdq(l,m-1,f,l1-1); 142 cdq(m+1,r,l1,t); 143 end; 144 145 begin 146 readln(n,m); 147 for i:=1 to m do 148 begin 149 readln(a[i].op,a[i].l,a[i].r,a[i].k); 150 a[i].p:=i; 151 if a[i].op=1 then 152 begin 153 inc(t); 154 c[t]:=a[i].k; 155 end; 156 end; 157 sort(1,t); 158 p:=1; 159 d[1]:=c[1]; 160 for i:=2 to t do 161 if c[i]<>c[i-1] then 162 begin 163 inc(p); 164 d[p]:=c[i]; 165 end; 166 167 fillchar(c,sizeof(c),0); 168 cdq(1,p,1,m); 169 for i:=1 to m do 170 if ans[i]<>0 then writeln(d[ans[i]]); 171 end.