HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的。

本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时。

然后修补了两个地方就过了,具体修改的地方请参看程序。

知道最大值段和最小值段,然后修补一下就能过了。不是特别难的题目。

#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;

const int SIZE = 200002;
const int TREESIZE = SIZE + (SIZE<<1);
int N, M, P;
int segTree[TREESIZE];
int smallest[TREESIZE];
int largest[TREESIZE];

inline int lChild(int rt) { return rt<<1; }
inline int rChild(int rt) { return rt<<1|1; }

void build(int l, int r, int rt)
{
	segTree[rt] = 0;
	smallest[rt] = 0;
	largest[rt] = 0;
	if (l == r) return ;

	int m = l + ((r-l)>>1);
	build(l, m, lChild(rt));
	build(m+1, r, rChild(rt));
}

inline void pushUp(int rt)
{
	smallest[rt] = min(smallest[lChild(rt)], smallest[rChild(rt)]);
	largest[rt] = max(largest[lChild(rt)], largest[rChild(rt)]);
}

inline void pushDown(int rt)
{
	if(segTree[rt])
	{
		int l = lChild(rt), r = rChild(rt);
		largest[l] += segTree[rt];
		largest[r] += segTree[rt];
		smallest[l] += segTree[rt];
		smallest[r] += segTree[rt];
		segTree[l] += segTree[rt];
		segTree[r] += segTree[rt];
		segTree[rt] = 0;
	}
}

void update(int L, int R, int val, int l, int r, int rt)
{
	if (L <= l && r <= R)
	{
		if(largest[rt] < P)
		{
			smallest[rt] += val;
			largest[rt] += val;
			segTree[rt] += val;
			return ;
		}
		if(smallest[rt] >= P)
		{
			smallest[rt] += val<<1;
			largest[rt] += val<<1;
			segTree[rt] += val<<1;
			return;
		}
	}

	//if (r < L || R < l) return;//在这里判断也会超时
	pushDown(rt);

	int m = l + ((r-l)>>1);
	if (L <= m) update(L, R, val, l, m, lChild(rt));
	if (m < R) update(L, R, val, m+1, r, rChild(rt));

	pushUp(rt);
}

inline void pushDown_2(int rt)
{
	if (segTree[rt])
	{
		segTree[lChild(rt)] += segTree[rt];
		segTree[rChild(rt)] += segTree[rt];
	}
}

void printTree(int l, int r, int rt)
{
	if (l == r)
	{
		if (l != N) printf("%d ", segTree[rt]);
		else printf("%d\n", segTree[rt]);
		return ;		//记得返回!
	}
	pushDown_2(rt);

	int m = l + ((r-l)>>1);
	printTree(l, m, lChild(rt));
	printTree(m+1, r, rChild(rt));
}

int main()
{
	int a, b, c;
	while (scanf("%d %d %d", &N, &M, &P) != EOF)
	{
		build(1, N, 1);
		//memset(largest, 0, sizeof(largest)); 这样写反而超时
		//memset(smallest, 0, sizeof(smallest));
		//memset(segTree, 0, sizeof(segTree));
		while (M--)
		{
			scanf("%d %d %d", &a, &b, &c);
			update(a, b, c, 1, N, 1);
		}
		printTree(1, N, 1);
	}
	return 0;
}

HDU 4107 Gangster Segment Tree线段树,布布扣,bubuko.com

时间: 2024-10-17 19:52:19

HDU 4107 Gangster Segment Tree线段树的相关文章

SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)

http://www.spoj.com/problems/SEGSQRSS/ SPOJ Problem Set (classical) 11840. Sum of Squares with Segment Tree Problem code: SEGSQRSS Segment trees are extremely useful.  In particular "Lazy Propagation" (i.e. see here, for example) allows one to c

XTU1238 Segment Tree (线段树&#183;区间最值更新)

对一个数组有四种操作 1: 将区间[ l, r] 中的所有值都加上c 2:将区间 [l, r] 中所有比c大的值改为c 3:将区间 [l, r] 中所有比c小的值改为c 4:输出区间 [l, r] 中所有数的最小值和最大值 对每个操作4输出对应最小值和最大值基础的线段树  在湘潭卡了好久没写出来  线段树维护三个值 区间最大值 maxv, 区间最小值minv, 区间增加的值add  操作1是... http://www.worlduc.com/blog2012.aspx?bid=44692767

HDU 1698 Just a Hook (线段树 成段更新 lazy-tag思想)

题目链接 题意: n个挂钩,q次询问,每个挂钩可能的值为1 2 3,  初始值为1,每次询问 把从x到Y区间内的值改变为z.求最后的总的值. 分析:用val记录这一个区间的值,val == -1表示这个区间值不统一,而且已经向下更新了, val != -1表示这个区间值统一, 更新某个区间的时候只需要把这个区间分为几个区间更新就行了, 也就是只更新到需要更新的区间,不用向下更新每一个一直到底了,在更新的过程中如果遇到之前没有向下更新的, 就需要向下更新了,因为这个区间的值已经不统一了. 其实这就

hdu 1394 Minimum Inversion Number 线段树 点更新

// hdu 1394 Minimum Inversion Number 线段树 点更新 // // 典型线段树的单点更新 // // 对于求逆序数,刚开始还真的是很年轻啊,裸的按照冒泡排序 // 求出最初始的逆序数,然后按照公式递推,结果就呵呵了 // // 发现大牛都是用线段树和树状数组之类的做的,而自己又在学 // 线段树,所以就敲了线段树. // // 线段树的节点保存一段区间( L,R )内0,1...n一共出现了多少个. // 因为每个数是0,1,2...n-1且没有重复的数字. /

HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

Problem A : Counting Squares From:HDU, 1264 Problem Description Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) that specify the opposite corners of a rectangle. All coordinates will be integers in t

HDU 1556 Color the ball 线段树更新区间查点

点击打开链接 Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9120    Accepted Submission(s): 4665 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽

hdu 4902 Nice boat(线段树区间修改,输出最终序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his peopl

HDU 1754 I Hate It(线段树)

Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目. 学生ID编号分别从1编到N. 第二

hdu 1754 I Hate It 线段树 点修改

// hdu 1754 I Hate It 线段树 点修改 // // 不多说,裸的点修改 // // 继续练 #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #i