[POJ 3468] A Simple Problem with Integers [线段树-动态建树版]

本文介绍了一种动态裸线段树的实现方法,通过预分配内存的方式避免了频繁的内存申请与释放,提高了程序效率。该实现支持区间更新与查询操作,并详细展示了如何进行懒惰传播以优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

裸线段树...动态建树版...

#include <cstdio>
#include <cstring>

using namespace std;

struct Node;
Node *p;

struct Node {
	int l,r;
	long long sum,lazy;
	Node *ls,*rs;
	Node() {}
	Node(int l,int r) {
		sum=lazy=0;
		ls=rs=NULL;
		this->l=l;
		this->r=r;
	}
	void update() {
		if (l!=r) {
			int t=(l+r)/2;
			if (ls==NULL) ls=new(p++)Node(l,t);
			if (rs==NULL) rs=new(p++)Node(t+1,r);
			ls->lazy+=lazy;
			rs->lazy+=lazy;
		}
		sum+=lazy*(r-l+1);
		lazy=0;
	}
	void *operator new (size_t,void *p) {
		return p;
	}
};

Node a[300100];
Node *root;
int n,q;

void add(Node *from,int l,int r,int x) {
	if (from->l==l&&from->r==r) {
		from->lazy+=x;
		return;
	}
	int t=(from->l+from->r)/2;
	if (from->ls==NULL) from->ls=new(p++)Node(from->l,t);
	if (from->rs==NULL) from->rs=new(p++)Node(t+1,from->r);
	from->sum+=x*(r-l+1);
	if (r<=t) add(from->ls,l,r,x);
	else if (t<l) add(from->rs,l,r,x);
	else {
		add(from->ls,l,t,x);
		add(from->rs,t+1,r,x);
	}
}
long long get(Node *from,int l,int r) {
	from->update();
	//printf("%d %d %d: %lld\n",(int)(from-a),l,r,from->sum);
	if (from->l==l&&from->r==r) return from->sum;
	int t=(from->l+from->r)/2;
	if (r<=t) return get(from->ls,l,r);
	if (t<l) return get(from->rs,l,r);
	return get(from->ls,l,t)+get(from->rs,t+1,r);
}

int main() {
	int i,x,y,z;
	long long ans;
	char c;
	while (scanf("%d%d",&n,&q)!=EOF) {
		p=&a[0];
		root=new(p++)Node(1,n);
		for (i=1;i<=n;i++) {
			scanf("%d",&x);
			add(root,i,i,x);
		}
		/*
		for (i=0;&a[i]<p;i++) {
			printf("--%d\n",i);
			printf("l=%d r=%d\n",a[i].l,a[i].r);
			printf("sum=%lld lazy=%lld\n",a[i].sum,a[i].lazy);
			printf("ls=%d rs=%d\n",(int)(a[i].ls-a),(int)(a[i].rs-a));
			printf("\n");
		}
		*/
		for (i=0;i<q;i++) {
			scanf(" %c",&c);
			if (c=='Q') {
				scanf("%d%d",&x,&y);
				printf("%lld\n",get(root,x,y));
			} else {
				scanf("%d%d%d",&x,&y,&z);
				add(root,x,y,z);
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值