线段树,未过样例,求调
  • 板块学术版
  • 楼主realheizi
  • 当前回复7
  • 已保存回复7
  • 发布时间2024/8/12 10:45
  • 上次更新2024/8/12 11:28:04
查看原帖
线段树,未过样例,求调
780067
realheizi楼主2024/8/12 10:45

原题 P3372 想要做到区间修改和区间查询O(logN)复杂度 求指正 代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int n,m,w[N];
struct node{//代表一个节点 
	int l,r,sum,add;//代表左右端点和区间和 
}tr[N*4];
//变量add代表“记账本”
//当区间修改时,如果x-y区间完全覆盖a-b区间
//先修改x-y区间的sum值,同时记在记账本上,然后返回 
// 下次需要查询a-b区间时,再下发欠下的值
//此做法可使修改与查询的时间复杂度都控制到O(logn) 
void pushup(int p){//向上更新 
	tr[p].sum=tr[p*2].sum+tr[p*2+1].sum;
} 
void pushdown(int p){//向下更新 
	if(tr[p].add){
		int num=tr[p].add*(tr[p*2].r-tr[p*2].l+1);
		tr[p*2].sum+=num,tr[p*2+1].sum+=num;
		tr[p*2].add+=tr[p].add,tr[p*2+1].add+=tr[p].add;
		tr[p].add=0;
	}
}
void build(int p,int l,int r){//建树 
	tr[p]={l,r,w[l],0};
	if(l==r) return;//是叶子就返回
	else{//不是就裂开 
		int m=(l+r)/2;
		build(p*2,l,m);
		build(p*2+1,m+1,r);
		pushup(p); 
	} 
}
void update(int p,int x,int y,int k){//x-y为节点位置,k为修改的值 
	if(tr[p].l>=x&&tr[p].r<=y){
		tr[p].sum+=(tr[p].r-tr[p].l+1)*k;
		tr[p].add+=k;
		return;
	} 
	else{
		pushdown(p);
		int m=(tr[p].l+tr[p].r)/2;
		if(x<=m) update(p*2,x,y,k);
		else update(p*2+1,x,y,k);
		pushup(p);		
	}
}
int query(int p,int x,int y){//区间查询 
	if(x<=tr[p].l&&tr[p].r<=y) return tr[p].sum;
	int m=(tr[p].l+tr[p].r)/2;//区间覆盖了当前节点则返回不覆盖就裂开 
	pushdown(p);
	int sum=0;
	if(x<=m) sum+=query(p*2,x,y);
	else sum+=query(p*2+1,x,y);
	return sum;
} 
int main(){
	ios::sync_with_stdio(false);	
	int a,x,y,k;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>w[i];
	build(1,1,n);
	while(m--){
		cin>>a>>x>>y;
		if(a==1){
			cin>>k;
			update(1,x,y,k);
		}
		else{
			cout<<query(1,x,y)<<endl;
		}
	}
	return 0;
} 
2024/8/12 10:45
加载中...