[BZOJ3343]教主的魔法|分块

Description

  教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N。
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[L, R](1≤L≤R≤N)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第L(R)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [L, R] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
 
  分块算法是指把一个序列分成sqrt(n)块,每块正好有sqrt(n)个元素
  对于这道题,我们先将每个数按顺序分到一个块中,维护每个块内部的单调性
  对于一个M操作,我们把l,r中间的块整块作一个加法的标记,对于两头的直接暴力标
  整块不超过sqrt(n)块,两头的也不超过sqrt(n)个元素,所以时间复杂度还是O(sqrt(n))
  对于A操作,对于暴力的部分很容易统计,对于整块的由于我们之前维护好了单调性,直接二分查找就可以了
  但是这里不要忽略了之前作的add标记
  
  
  1 {
  2     Chunk.
  3 }
  4 
  5 program bzoj3343;
  6 const maxn=1000010;maxm=1010;
  7 var n,q,m,block,x,y,z,i:longint;
  8     ch:char;
  9     a,b,pos:array[-1..maxn]of longint;
 10     add:array[-1..maxm]of longint;
 11 
 12 function min(a,b:longint):longint;
 13 begin
 14     if a<b then exit(a) else exit(b);
 15 end;
 16 
 17 procedure qsort(L,R:longint);
 18 var i,j,mid:longint;
 19 begin
 20     i:=L;j:=R;mid:=b[random(R-L+1)+L];
 21     repeat
 22         while (i<R)and(b[i]>mid) do inc(i);
 23         while (L<j)and(b[j]<mid) do dec(j);
 24         if i<=j then
 25         begin
 26             b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
 27             inc(i);dec(j);
 28         end;
 29     until i>j;
 30     if i<R then qsort(i,R);
 31     if L<j then qsort(L,j);
 32 end;
 33 
 34 procedure new(p:longint);
 35 var l,r,i:longint;
 36 begin
 37     l:=(p-1)*block+1;r:=min(p*block,n);
 38     for i:=l to r do b[i]:=a[i];
 39     qsort(l,r);
 40 end;
 41 
 42 procedure update(x,y,z:longint);
 43 var i:longint;
 44 begin
 45     if pos[x]=pos[y] then
 46         for i:=x to y do inc(a[i],z) else
 47     begin
 48         for i:=x to pos[x]*block do inc(a[i],z);
 49         for i:=(pos[y]-1)*block+1 to y do inc(a[i],z);
 50     end;
 51     for i:=pos[x]+1 to pos[y]-1 do inc(add[i],z);
 52     new(pos[x]);new(pos[y]);
 53 end;
 54 
 55 function find(x,y:longint):longint;
 56 var L,R,mid:longint;
 57 begin
 58     find:=(x-1)*block;
 59     L:=(x-1)*block+1;R:=x*block;
 60     while L<=R do
 61     begin
 62         mid:=(L+R) >> 1;
 63         if b[mid]>=y then
 64         begin
 65             find:=mid;L:=mid+1;
 66         end else R:=mid-1;
 67     end;
 68     dec(find,(x-1)*block);
 69 end;
 70 
 71 function query(x,y,z:longint):longint;
 72 var tot,i:longint;
 73 begin
 74         tot:=0;
 75     if pos[x]=pos[y] then
 76     begin    for i:=x to y do if a[i]>=z then inc(tot);end else
 77     begin
 78         for i:=x to pos[x]*block do if a[i]>=z then inc(tot);
 79         for i:=(pos[y]-1)*block+1 to y do if a[i]>=z then inc(tot);
 80     end;
 81     for i:=pos[x]+1 to pos[y]-1 do inc(tot,find(i,z-add[i]));
 82         exit(tot);
 83 end;
 84 
 85 begin
 86     readln(n,q);
 87     fillchar(add,sizeof(add),0);
 88     block:=trunc(sqrt(n));
 89     for i:=1 to n do
 90     begin
 91         read(a[i]);
 92         pos[i]:=(i-1) div block+1;//pos[i]表示第i个数所在的块
 93     end;
 94         readln;
 95     if n mod block=0 then m:=n div block else m:=n div block +1;
 96     for i:=1 to m do new(i);
 97         for i:=1 to q do
 98     begin
 99         read(ch);
100         if ch='M' then
101         begin
102             readln(x,y,z);
103             update(x,y,z);
104         end else
105         begin
106             readln(x,y,z);
107             writeln(query(x,y,z));
108         end;
109     end;
110 end.
原文地址:https://www.cnblogs.com/mjy0724/p/4424011.html