对于区间操作的问题,部分可以用分块来做
事实上分块还是蛮简单的,主要是看分块之后怎么样进行处理,它很灵活,没有固定的模式
还是拿题目来举例吧
Bzoj 2002 Bzoj 3065
Bzoj 2002 分块版
#include"cstdio"
#include"cmath"
#define Maxn 200005
int st[Maxn],pt[Maxn],belong[Maxn],k[Maxn];
int l[1000],r[1000];
inline int read() {
int x = 0,f = 1;char ch;
ch = getchar();
while (ch>'9' || ch<'0') {if (ch == '-') f = -1;ch = getchar();}
while (ch<='9' && ch>='0') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void init(int n,int block) {
for (int i = 1;i <= n;i ++) {
k[i] = read();
belong[i] = (i-1)/block + 1;
}
int cnt;
if (n%block) cnt = n/block + 1; else
cnt = n/block;
for (int i = 1;i <= cnt;i ++) {
l[i] = (i-1)*block + 1;
r[i] = i*block;
}
r[cnt] = n;
for (int i = n;i > 0;i --)
if (i+k[i] > n) st[i] = 1; else
if (belong[i] == belong[i+k[i]])
st[i] = st[i+k[i]]+1,pt[i] = pt[i+k[i]]; else
st[i] = 1,pt[i] = i+k[i];
}
int cal(int x) {
int ans = 0;
while (1) {
ans += st[x];
if (!pt[x]) break;
x = pt[x];
}
return ans;
}
int main() {
int n = read(),block = sqrt(n);
init(n,block);
int m = read();
while (m--) {
int f = read(),x = read()+1,y;
if (f == 1) printf("%d\n",cal(x)); else {
k[x] = y = read();
for(int i = x;i >= l[belong[x]];i --)
if (i+k[i] > n) st[i] = 1,pt[i] = 0; else
if (belong[i] == belong[i+k[i]])
st[i] = st[i+k[i]]+1,pt[i] = pt[i+k[i]]; else
st[i] = 1,pt[i] = i+k[i];
}
}
return 0;
}
Bzoj 3065 自己模大佬的分块版
#include"cstdio"
#include"algorithm"
#include"cmath"
using namespace std;
int a[1005][1005],b[1005][1005],inum[100002];
int idx,ipos,tot[1005],nxt[1005];
int cnt,N,B,lastans;
typedef pair<int,int> abcd;
abcd lp,rp;
inline void shuchu() {
for (int i = 1;i <= cnt;i ++) {
for (int j = 1;j <= tot[i];j ++)
printf("%d ",b[i][j]);
printf("\n");
}
printf("\n");
}
inline char read() {
char ch = getchar();
while(ch > 'Z' || ch < 'A') ch = getchar();
return ch;
}
inline abcd kth(int k) {
for (int i = 1;i;i = nxt[i]) {
if (!nxt[i] && k>tot[i])
return abcd(i,k);
if (k>tot[i])
k -= tot[i];else
return abcd(i,k);
}
}
bool check(int mid,int K) {
int ret = 0;
if (lp.first == rp.first) {
for(int i = lp.second;i <= rp.second;i ++)
if(a[lp.first][i] <= mid) ret++;
return ret>=K;
}
for(int i = lp.second;i <= tot[lp.first];i ++)
if (a[lp.first][i] <= mid) ret++;
for(int i= 1;i <= rp.second;i ++)
if (a[rp.first][i] <= mid) ret++;
for (int i = nxt[lp.first];i != rp.first;i = nxt[i])
ret+=upper_bound(b[i]+1,b[i]+tot[i]+1,mid) - b[i] - 1;
return ret>=K;
}
void Query() {
int l,r,K;
//abcd lp,rp;
scanf("%d%d%d",&l,&r,&K);
l^=lastans,r^=lastans,K^=lastans;
lp = kth(l),rp = kth(r);
int L=-1,R=70000,MID;
while (L+1<R)
if(check(MID = (L+R)>>1,K))
R = MID; else L = MID;
//printf("Q %d %d %d\n",l,r,K);
//shuchu();
printf("%d\n",lastans = R);
}
void Modify() {
int x,val,t;
scanf("%d%d",&x,&val);
x^=lastans,val^=lastans;
abcd p = kth(x);
idx = p.first;
t = a[idx][p.second];
ipos = lower_bound(b[idx]+1,b[idx]+tot[idx]+1,t) - b[idx];
a[idx][p.second] = val;
b[idx][ipos] = val;
while (ipos-1>=1 && b[idx][ipos]<b[idx][ipos-1])
swap(b[idx][ipos],b[idx][ipos-1]),ipos--;
while (ipos+1<=tot[idx] && b[idx][ipos]>b[idx][ipos+1])
swap(b[idx][ipos],b[idx][ipos+1]),ipos++;
//printf("M %d %d\n",x,val);
//shuchu();
}
void Depth(int idx) {
cnt ++;
for (int i = B+1;i <= tot[idx];i ++)
b[cnt][++tot[cnt]]=a[idx][i],a[cnt][tot[cnt]] = a[idx][i],a[idx][i]=0;
sort(b[cnt]+1,b[cnt]+tot[cnt]+1);
tot[idx] -= B;
for (int i = 1;i <= tot[idx];i ++)
b[idx][i] = a[idx][i];
sort(b[idx]+1,b[idx]+tot[idx]+1);
nxt[cnt] = nxt[idx];nxt[idx] = cnt;
}
void Insert() {
int x,val;
scanf("%d%d",&x,&val);
x^=lastans,val^=lastans;
abcd p = kth(x);
idx = p.first;
for (int i = tot[idx]+1;i>p.second;i --)
a[idx][i] = a[idx][i-1];
a[idx][p.second] = val;
b[idx][++tot[idx]] = val;
ipos = tot[idx];
while (ipos-1>=1 && b[idx][ipos]<b[idx][ipos-1])
swap(b[idx][ipos],b[idx][ipos-1]),ipos--;
while (ipos+1<=tot[idx] && b[idx][ipos]>b[idx][ipos+1])
swap(b[idx][ipos],b[idx][ipos+1]),ipos++;
if (tot[idx]>=2*B) Depth(idx);
//printf("I %d %d\n",x,val);
//shuchu();
}
int main() {
//freopen("t.in","r",stdin);
int p;
scanf("%d",&N);
for (int i = 1;i <= N;i ++) scanf("%d",&inum[i]);
B = sqrt(N),cnt = (N-1)/B + 1;
for (int i = 1;i <= N;i ++) {
idx = (i-1)/B + 1;
a[idx][++tot[idx]] = inum[i];
b[idx][tot[idx]] = inum[i];
}
for (int i = 1;i <= cnt;i ++)
sort(b[i]+1,b[i]+tot[i]+1),nxt[i] = i+1;
nxt[cnt] = 0;
scanf("%d",&p);
while (p--) {
char ch;
//getchar();
ch = read();
if (ch == 'Q')
Query(); else if (ch == 'M')
Modify(); else
Insert();
}
return 0;
}