蒟蒻分块求助
  • 板块学术版
  • 楼主zhoukangyang
  • 当前回复21
  • 已保存回复21
  • 发布时间2020/6/13 09:55
  • 上次更新2023/11/7 00:46:09
查看原帖
蒟蒻分块求助
173660
zhoukangyang楼主2020/6/13 09:55

LOJ题面

题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,询问区间内小于某个值 x 的元素个数。

输入格式
第一行输入一个数字 n。

第二行输入 n 个数字,第 i 个数字为 ai,以空格隔开。

接下来输入 n 行询问,每行输入四个数字 opt、l、r、c,以空格隔开。

若 opt=0,表示将位于 [l,r] 的之间的数字都加 c。

若 opt=1,表示询问 [l,r] 中,小于 c2 的数字的个数。

输出格式
对于每次询问,输出一行一个数字表示答案。

样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
数据范围与提示

对于 100% 的数据,1≤n≤50000、−231≤others、ans≤−231−1。

内存限制:256 MB

时间限制:500 ms
#include<bits/stdc++.h>
#define int long long
#define N 110000
using namespace std;
int n,m,spa,splx,sply,splz,rot[N];
int kuai,lazy[N];
int s[N];
struct node {
	int son[2],siz,val,key;
} q[N];
void upd(int x) {
	q[x].siz=q[q[x].son[0]].siz+q[q[x].son[1]].siz+1;
}
int new_root(int value,int fn) {
	q[fn].siz=1,q[fn].val=value,q[fn].key=rand(),q[fn].son[0] = q[fn].son[1] = 0;
	return fn;
}
int merge(int x,int y) { //x < y
	if(!x||!y) return x+y;
	if(q[x].key<q[y].key) {
		q[x].son[1]=merge(q[x].son[1],y),upd(x);
		return x;
	} else {
		q[y].son[0]=merge(x,q[y].son[0]),upd(y);
		return y;
	}
}
void split(int now,int k,int &x,int &y) {
	if(!now) x=y=0;
	else {
		if(q[now].val<=k) x=now,split(q[now].son[1],k,q[now].son[1],y);
		else y=now,split(q[now].son[0],k,x,q[now].son[0]);
		upd(now);
	}
}
void ins(int us,int fn,int &root) {
	split(root,us,splx,sply),root=merge(merge(splx,new_root(us,fn)),sply);
}
int shan(int us,int &root) {
	split(root,us,splx,sply),split(splx,us-1,splx,splz);
	int Ans = splz;
	splz = merge(q[splz].son[0],q[splz].son[1]);
	root=merge(merge(splx,splz),sply);
	return Ans;	
}
int fkth(int us,int &root) {
	split(root,us-1,splx,sply);
	int Ans = q[splx].siz;
	root=merge(splx,sply);
	return Ans;
}
void kbj(int us,int &kz,int &ky) {
	kz = kuai*(us-1) + 1;
	ky = min(n,kuai*us);
} 
signed main() {
	srand(1919810);
	int opt,cini,L,R,C;
	scanf("%lld",&n),m=n,kuai=sqrt(n);
	for(int i = 1; i <= n; i++) scanf("%lld",&s[i]),ins(s[i],i,rot[(i+kuai-1)/kuai]);
	while(m--) {
		scanf("%lld%lld%lld%lld",&opt,&L,&R,&C);
		if(opt == 1) {
			int Ans = 0;
			for(int i = 1; i <= (n+kuai-1)/kuai; i++) {
				int ned = C*2-lazy[i];
				int fL,fR;
				kbj(i,fL,fR);
				if(fR<L) continue;
				if(fL>R) continue;
				if(fL>=L&&fR<=R) {
					Ans += fkth(ned,rot[i]);					
					continue;
				}
				if(fL<L)
					for(int j = L; j <= fR; j++) Ans += (s[j] < ned);
				else 
					for(int j = fL; j <= R; j++) Ans += (s[j] < ned);
			}
			printf("%lld\n",Ans);
		}
		else {
			for(int i = 1; i <= (n+kuai-1)/kuai; i++) {
				int fL,fR;
				kbj(i,fL,fR);
				if(fR<L) continue;
				if(fL>R) continue;
				if(fL>=L&&fR<=R) {
					lazy[i] += C;					
					continue;
				}
				if(fL<L)
					for(int j = fL; j <= R; j++) {
						int mmp = shan(s[j],rot[i]);
						s[j] += C , ins(s[j],mmp,rot[i]);
					}
				else 
					for(int j = fL; j <= R; j++) {
						int mmp = shan(s[j],rot[i]);
						s[j] += C , ins(s[j],mmp,rot[i]);
					}
			}
		}
	}
	return 0;
}
2020/6/13 09:55
加载中...