首页 > 代码库 > hdu 4107卡时线段树

hdu 4107卡时线段树

核心思想就是节点上记录最大值和最小值,如果max<p或min>=p时,只在节点改变add值,不用往子树遍历;否则就往子树进行递归。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>

using namespace std;

const int maxn = 2e5+50;
int N, P;

struct node{
	int l, r, Min, Max, add;
	int mid() { return (l+r)/2; }
}tree[maxn<<2];

int p, n;
void buildTree(int l, int r, int rt)
{
	tree[rt].l = l;
	tree[rt].r = r;
	tree[rt].add = 0;
	tree[rt].Min = 0;
	tree[rt].Max = 0;
	if(l == r) return ;
	int mid = tree[rt].mid();
	buildTree(l, mid, rt<<1);
	buildTree(mid+1, r, rt<<1|1);
}

void update(int l, int r, int rt, int L, int R, int add)
{
	if(L <= l && R >= r)
	{
		if(tree[rt].Max < P)
		{
			tree[rt].add += add;
			tree[rt].Min += add;
			tree[rt].Max += add;
			return ;
		}
		else if(tree[rt].Min >= P)
		{
			tree[rt].add += 2*add;
			tree[rt].Min += 2*add;
			tree[rt].Max += 2*add;
			return ;
		}
	}
	if(tree[rt].add){
		tree[rt<<1].add += tree[rt].add;
		tree[rt<<1].Min += tree[rt].add;
		tree[rt<<1].Max += tree[rt].add; 
		tree[rt<<1|1].add += tree[rt].add;
		tree[rt<<1|1].Min += tree[rt].add;
		tree[rt<<1|1].Max += tree[rt].add;
		
		tree[rt].add = 0;
	}
	if(l == r) return ;
	int mid = tree[rt].mid();
	if(L <= mid) update(l, mid, rt<<1, L, R, add);
	if(R > mid) update(mid+1, r, rt<<1|1, L, R, add);
	
	tree[rt].Min = min(tree[rt<<1].Min, tree[rt<<1|1].Min);
	tree[rt].Max = max(tree[rt<<1].Max, tree[rt<<1|1].Max);
} 

void query(int l, int r, int rt)
{
	if(tree[rt].Min == tree[rt].Max){
		for(int i = l; i <= r; i ++)
			printf( i == N ? "%d\n" : "%d ", tree[rt].Min );
		return ;
	}
	if(tree[rt].add)
	{
		tree[rt<<1].add += tree[rt].add;
		tree[rt<<1].Min += tree[rt].add;
		tree[rt<<1].Max += tree[rt].add; 
		tree[rt<<1|1].add += tree[rt].add;
		tree[rt<<1|1].Min += tree[rt].add;
		tree[rt<<1|1].Max += tree[rt].add;
		
		tree[rt].add = 0;
	}	
	if(l == r) return ;
	int mid = tree[rt].mid();
	query(l, mid, rt<<1);
	query(mid+1, r, rt<<1|1);
}

int main()
{
	int n, m, p;
	int a, b, c;
	while(~scanf("%d%d%d", &n, &m, &p))
	{
		N = n;
		P = p;
		buildTree(1, n, 1);
		for(int i = 0; i < m; i ++)
		{
			scanf("%d%d%d", &a, &b, &c);
			update(1, n, 1, a, b, c);
		}
		query(1, n, 1);
	}
}