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);
	}
}
时间: 2024-10-13 08:35:18

hdu 4107当卡段树的相关文章

HDU ACM 4578 Transformation-&amp;gt;段树-间隔的变化

分析:复杂的经营分部树. 只有一个查询操作,这是要求[l,r]的数量之间p钍总和.并不是所有的查询所有节点,会议TLE.最好的是查询部件[a.b].所有这个区间值我们是平等的,即能返回(b-a+1)*val 的值.区间内全部值都同样的情况的区间.对于置初值和加乘操作.分两种情况:1.当为置初值操作.直接覆盖区间就可以.并把标记的加乘操作赋为初始值.2.当为加乘操作时.先推断当前区间段是否为同样的值,是的话直接加乘,维护这个同样的值就可以.假设不同样,看区间是否已有加乘标记,把这个加乘标记一直传递

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 = 2

HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的. 本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时. 然后修补了两个地方就过了,具体修改的地方请参看程序. 知道最大值段和最小值段,然后修补一下就能过了.不是特别难的题目. #include <stdio.h> #include <string> #include <algorithm> using namespace std; c

HDU 3966 Aragorn&#39;s Story (树链点权剖分,成段修改单点查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. 1 //树链剖分 边权修改 单点查询 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cstdio> 6 using namespace std; 7 const int M

HDU 4902 Nice boat(线段树)

HDU Nice boat 题目链接 题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

HDU 3308 LCIS(线段树)

Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index counting from 0)Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. Input T in the first line, indicating

HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11551    Accepted Submission(s): 4906 Problem Description There are several ancient Greek texts that contain descriptions of the fabled

HDU-5172-GTY&#39;s gay friends-线段树单点更新

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172 题意:给出n个数,m个询问,问你[l,r]区间内是否为1到r-l+1的全排列. 大小很容易我们通过记录前缀和很容易求出来,但是关键是去重. 考虑线段树做法,我们记录每个点的靠左最近的相同元素的位置,然后求 整个区间的最大值(即最大的前驱)如果小于l,即满足条件,输出YES. 好吧,其实这个题目我是搜的RMQ算法出来的,因为我想练一下RMQ算法,所以我就看了一下别人的博客,自己也写了一下,结果死