动态开点线段树模板求调
  • 板块学术版
  • 楼主LolaPeppa
  • 当前回复2
  • 已保存回复2
  • 发布时间2024/11/6 21:40
  • 上次更新2024/11/7 11:45:11
查看原帖
动态开点线段树模板求调
1314900
LolaPeppa楼主2024/11/6 21:40

动态开点线段树模板。支持区间加一个数,查询区间和。Wrong Answer,求调/kel

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>

using namespace std;

typedef long long ll;

const int N = 200010;

int n, q, nn = 1;
struct Node {
	int sum, tag, lc, rc;
}tr[100010];

void pushUp(int u) {
	if (tr[u].lc) tr[u].sum = tr[tr[u].lc].sum;
	if (tr[u].rc) tr[u].sum += tr[tr[u].rc].sum;
}

void movetag(int u, int l, int r, int k) {
	tr[u].sum += (r - l + 1) * k;
	tr[u].tag += k;
}

void pushDown(int u, int l, int r) {
	if (tr[u].tag) {
		int mid = (l + r) >> 1;
		if (tr[u].lc) movetag(tr[u].lc, l, mid, tr[u].tag);
		if (tr[u].rc) movetag(tr[u].rc, mid + 1, r, tr[u].tag);
		tr[u].tag = 0;
	}
}

void update(int u, int l, int r, int ql, int qr, int k) {
	if (l >= ql && r <= qr) {
		movetag(u, l, r, k);
		return;
	}
	int mid = (l + r) >> 1;
	pushDown(u, l, r);
	if (ql <= mid) {
		if (tr[u].lc == 0) tr[u].lc = ++nn;
		update(tr[u].lc, l, mid, ql, qr, k);
	}
	if (qr > mid) {
		if (tr[u].rc == 0) tr[u].rc = ++nn;
		update(tr[u].rc, mid + 1, r, ql, qr, k);
	}
	pushUp(u);
}

int query(int u, int l, int r, int ql, int qr) {
	if (u == 0 || tr[u].sum == 0) return 0;
	if (l >= ql && r <= qr) return tr[u].sum;
	int mid = (l + r) >> 1, res = 0;
	pushDown(u, l, r);
	if (ql <= mid) res = query(tr[u].lc, l, mid, ql, qr);
	if (qr > mid) res += query(tr[u].rc, mid + 1, r, ql, qr);
	return res;
}

int main() {
	scanf("%d%d", &n, &q);
	while(q--) {
		int o, l, r;
		scanf("%d%d%d", &o, &l, &r);
		if (o == 1) {
			int k;
			scanf("%d", &k);
			update(1, 1, n, l, r, k);
		} else {
			printf("%d\n", query(1, 1, n, l, r));
		}
	}
	return 0;
}
2024/11/6 21:40
加载中...