玄关求助,又T又 Wa
  • 板块P3863 序列
  • 楼主wujingfey
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/11/23 17:02
  • 上次更新2024/11/23 19:46:30
查看原帖
玄关求助,又T又 Wa
637073
wujingfey楼主2024/11/23 17:02
/*
离线询问

动态维护分块数组表示 第i个数 的时间状态
把1操作挂在l和r+1上
按照序列下标从下往上扫
每次扫到 i 就把挂在 i 的操作运用在分块数组上
然后分块计算答案 

分块任务:区间加减,回答区间内大于 x-a[i] 的数个数 
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,a[N];
int st[N],ed[N],pos[N],t,len;
int ans[N];
struct NODE{
	int l,r,x,idx;
	//idx=0:修改操作
	//idx!=0:查询的编号 
};
vector<NODE> v[N],q[N];
int b[N],c[N],tag[N];//b原序列,c排序序列 
void update(int l,int r,int x){
	int pl=pos[l],pr=pos[r];
	if(pl==pr){
		for(int i=l;i<=r;i++) b[i]+=x;
		for(int i=st[pl];i<=ed[pl];i++)	c[i]=b[i];
		sort(c+st[pl],c+ed[pl]+1);
	}else{
		for(int i=l;i<=ed[pl];i++) b[i]+=x;
		for(int i=st[pl];i<=ed[pl];i++) c[i]=b[i];
		sort(c+st[pl],c+ed[pl]+1);
		//----------------------------
		for(int i=st[pr];i<=r;i++) b[i]+=x;
		for(int i=st[pr];i<=ed[pr];i++) c[i]=b[i];
		sort(c+st[pr],c+ed[pr]+1);
		//----------------------------
		for(int i=pl+1;i<=pr-1;i++) tag[i]+=x;
	}
}
void push(int x){
	for(int i=st[x];i<=ed[x];i++){
		b[i]+=tag[x];
		c[i]+=tag[x];
	}
	tag[x]=0;
}
int query(int l,int r,int x){
	int res=0,pl=pos[l],pr=pos[r];
	if(pl==pr){
		push(pl);
		for(int i=l;i<=r;i++){
			if(b[i]>=x) res++;
		}
		return res;
	}else{
		if(tag[pl]) push(pl);
		for(int i=l;i<=ed[pl];i++){
			if(b[i]>=x) res++;
		}
		//----------------------------
		if(tag[pr]) push(pr);
		for(int i=st[pr];i<=r;i++){
			if(b[i]>=x) res++;
		}
		//-----------------------------
		for(int i=pl+1;i<=pr-1;i++){
			int xx=lower_bound(c+st[i],c+ed[i]+1,x-tag[i])-c;
			res+=(ed[i]-xx+1);
		}
		return res;
	} 
}
signed main(){
//	freopen("P3863_1.in","r",stdin);
//	freopen("P3863.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=m;i++){
		int op,x,y,z;
		cin>>op;
		if(op==1){
			cin>>x>>y>>z;
			v[x].push_back({i,m,z,0});
			v[y+1].push_back({i,m,-z,0});
		}else{
			cin>>x>>y;//query:a[y]: [x->i-1]
			q[x].push_back({1,i-1,y,i});
		}
	}
	len=sqrt(n);
	t=n/len;
	if(n%len) t++;
	for(int i=1;i<=t;i++){
		st[i]=(i-1)*len+1;
		ed[i]=i*len;
	}
	ed[t]=n;
	for(int i=1;i<=t;i++){
		for(int j=st[i];j<=ed[i];j++){
			pos[j]=i;
		}
	}
	for(int i=1;i<=n;i++){
		ans[i]=-1;
	}
	for(int i=1;i<=n;i++){//枚举第i个数 
		for(auto p:v[i]){
			int l=p.l, r=p.r, x=p.x;
			update(l,r,x);
		}
		for(auto p:q[i]){
			int l=p.l, r=p.r, x=p.x, idx=p.idx;
			int res=query(l,r,x-a[i]);//查找多少个时间段内大于 x-a[i] 
			ans[idx]=res;
			if(a[i]>=x) ans[idx]++;//统计 t=0 的贡献 
		}
	}
	for(int i=1;i<=n;i++){
		if(ans[i]!=-1){
			cout<<ans[i]<<'\n';
		}
	}
	return 0;
}
2024/11/23 17:02
加载中...