6Luffy6

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

P3372 【模板】线段树 1

不引用懒惰标记的方法,会超时

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int nums[N];
typedef long long ll;
struct Tree {
	int l, r;
	ll sum;
	int tag;
}tree[N<<2];
void pushup(int u) {
	tree[u].sum = tree[u << 1].sum + tree[u << 1 | 1].sum;
}
void build(int u, int l, int r) {
	if (l == r) {
		tree[u] = { l,r,nums[l] };
		return;
	}
	tree[u] = { l,r };
	int mid = (l + r) >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	pushup(u);
}
void pushdown(int u, int ln, int rn) {
	if (tree[u].tag) {
		tree[u << 1].tag += tree[u].tag;
		tree[u << 1 | 1].tag += tree[u].tag;
		
		tree[u << 1].sum += tree[u].tag * ln;
		tree[u << 1 | 1].sum += tree[u].tag * rn;
		tree[u].tag = 0;
	}
}
ll query(int u, int L, int R) {
	int l = tree[u].l, r = tree[u].r;
	int mid = (l + r) >> 1;
	if (l >= L && r <= R) {
		return tree[u].sum;
	}
	pushdown(u, mid - l + 1, r - mid);//有懒惰标记时要下推标记 
	ll sum = 0;
	if (L <= mid) sum += query(u << 1, L, R);
	if (R > mid) sum += query(u << 1 | 1, L, R);
	return sum;
}

void modify_span(int u, int L,int R, int val) {
	int l = tree[u].l, r = tree[u].r;
	int mid = (l + r) >> 1;
	if (l == r) {
		tree[u].sum += val;
		return;
	}
	
	if(L <= mid)modify_span(u << 1, L, R, val);
	if(R > mid) modify_span(u << 1 | 1, L, R, val);

	pushup(u);
}
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> nums[i];
	}
	build(1,1,n);
	while (m--) {//操作数
		int op;
		cin>>op;
		if (op == 1) {
			int x, y, k;
			cin >> x >> y >> k;
			modify_span(1, x, y, k);
		}
		else {
			int x, y;
			cin >> x >> y;
			cout << query(1, x, y) << endl;
		}
	}
	return 0;
}


记得sum、query要开**long long **否则会WA

下面将介绍一种引入一种不超时的方法,时间复杂度变为O(nlogn)

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e6 + 10;
int nums[N];
typedef long long ll;
struct Tree {
	int l, r;
	ll sum;
	int tag;
}tree[N<<2];
void pushup(int u) {
	tree[u].sum = tree[u << 1].sum + tree[u << 1 | 1].sum;
}
void build(int u, int l, int r) {
	if (l == r) {
		tree[u] = { l,r,nums[l] };
		return;
	}
	tree[u] = { l,r };
	int mid = (l + r) >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	pushup(u);
}
void pushdown(int u, int ln, int rn) {
	if (tree[u].tag) {
		tree[u << 1].tag += tree[u].tag;
		tree[u << 1 | 1].tag += tree[u].tag;
		
		tree[u << 1].sum += tree[u].tag * ln;
		tree[u << 1 | 1].sum += tree[u].tag * rn;
		tree[u].tag = 0;
	}
}
ll query(int u, int L, int R) {
	int l = tree[u].l, r = tree[u].r;
	int mid = (l + r) >> 1;
	if (l >= L && r <= R) {
		return tree[u].sum;
	}
	pushdown(u, mid - l + 1, r - mid);//有懒惰标记时要下推标记 
	ll sum = 0;
	if (L <= mid) sum += query(u << 1, L, R);
	if (R > mid) sum += query(u << 1 | 1, L, R);
	return sum;
}

void modify_span(int u, int L,int R, int val) {
	int l = tree[u].l, r = tree[u].r;
	int mid = (l + r) >> 1;
	if (l >= L && r <= R) {
		tree[u].sum += (r - l + 1) * val;
		tree[u].tag += val;
		pushdown(u, mid - l + 1, r - mid);
		return;
	}
	
	pushdown(u, mid - l + 1, r - mid);
	if(L <= mid)modify_span(u << 1, L, R, val);
	if(R > mid) modify_span(u << 1 | 1, L, R, val);

	pushup(u);
}
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> nums[i];
	}
	build(1,1,n);
	while (m--) {//操作数
		int op;
		cin>>op;
		if (op == 1) {
			int x, y, k;
			cin >> x >> y >> k;
			modify_span(1, x, y, k);
		}
		else {
			int x, y;
			cin >> x >> y;
			cout << query(1, x, y) << endl;
		}
	}
	return 0;
}

posted on   极客三刀流  阅读(8)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示