hdu 5306 Gorgeous Sequence(线段树)

题目链接:hdu 5306 Gorgeous Sequence

和普通的线段树一样一个标记值T,然后另外加一个C值记录以u为根节点的子树下有多少个叶子节点被T值控制。每次修改时,dfs到叶子节点之后在修改该节点。维护sum值时只要额外加上T值控制下的节点。加了个输入外挂,时间少了将近1000ms。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1000000 + 5;
typedef long long ll;
#define lson(x) (x<<1)
#define rson(x) ((x<<1)|1)

/*********** input *************/
char *ch, *ch1, buf[40*1024000+5], buf1[40*1024000+5];
void read(int &x)   {
	for (++ch; *ch <= 32; ++ch);
	for (x = 0; '0' <= *ch; ch++)    x = x * 10 + *ch - '0';
}
/******************************/

struct Node {
	int L, R, M, T, C;
	ll S;
}nd[maxn << 2];;

inline void pushup(int u) {
	nd[u].M = max(nd[lson(u)].M, nd[rson(u)].M);
	nd[u].S = nd[lson(u)].S + nd[rson(u)].S;
	nd[u].C = nd[lson(u)].C + nd[rson(u)].C;
}

inline void maintain (int u, int alter) {
	if (nd[u].T != 0 && nd[u].T <= alter)
		return;
	nd[u].T = alter;
	if (nd[u].C != nd[u].R - nd[u].L + 1) {
		nd[u].M = alter;
		nd[u].S += 1LL * (nd[u].R - nd[u].L + 1 - nd[u].C) * alter;
		nd[u].C = nd[u].R - nd[u].L + 1;
	}
}

void dfs (int u, int alter) {
	if (nd[u].M <= alter)
		return;

	nd[u].T = 0;
	if (nd[u].L == nd[u].R) {
		nd[u].S = nd[u].M = nd[u].C = 0;
		return;
	}
	dfs(lson(u), alter);
	dfs(rson(u), alter);
	pushup(u);
}

inline void pushdown(int u) {
	if (nd[u].T == 0)
		return ;
	maintain(lson(u), nd[u].T);
	maintain(rson(u), nd[u].T);
}

void build (int u, int l, int r) {
	nd[u].L = l, nd[u].R = r, nd[u].T = 0;

	if (l == r) {
		read(nd[u].M);
		//scanf("%d", &nd[u].M);
		nd[u].T = nd[u].S = nd[u].M;
		nd[u].C = 1;
		return;
	}

	int mid = (l + r) >> 1;
	build (lson(u), l, mid);
	build (rson(u), mid + 1, r);
	pushup(u);
}

void modify (int u, int l, int r, int alter) {

	if (nd[u].M <= alter)
		return;

	if (l <= nd[u].L && nd[u].R <= r) {
		dfs(u, alter);
		maintain(u, alter);
		return;
	}

	int mid = (nd[u].L + nd[u].R) >> 1;
	pushdown(u);
	if (l <= mid)
		modify(lson(u), l, r, alter);
	if (r > mid)
		modify(rson(u), l, r, alter);
	pushup(u);
}

void query (int u, int l, int r, ll& sum, int& mx) {
	if (l <= nd[u].L && nd[u].R <= r) {
		sum = sum + nd[u].S;
		mx = max(mx, nd[u].M);
		return;
	}

	int mid = (nd[u].L + nd[u].R) >> 1;
	pushdown(u);
	if (l <= mid)
		query(lson(u), l, r, sum, mx);
	if (r > mid)
		query(rson(u), l, r, sum, mx);
	pushup(u);
}

int main () {

	ch = buf - 1;
	ch1 = buf1 - 1;
	fread(buf, 1, 1000 * 35 * 1024, stdin);  

	int cas, n, m, k, x, y, t, mx;
	ll s;
	read(cas);
	//scanf("%d", &cas);
	while (cas--) {
		read(n), read(m);
		//scanf("%d%d", &n, &m);
		build(1, 1, n);
		for (int i = 0; i < m; i++) {
			read(k), read(x), read(y);
			//scanf("%d%d%d", &k, &x, &y);
			if (k) {
				s = mx = 0;
				query(1, x, y, s, mx);
				if (k == 1)
					printf("%d\n", mx);
				else
					printf("%lld\n", s);
			} else {
				read(t);
				//scanf("%d", &t);
				modify(1, x, y, t);
			}
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 17:10:01

hdu 5306 Gorgeous Sequence(线段树)的相关文章

HDU 5306 Gorgeous Sequence[线段树区间最值操作]

Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2150    Accepted Submission(s): 594 Problem Description There is a sequence a of length n. We use ai to denote the i-th elemen

HDOJ 5306 Gorgeous Sequence 线段树

http://www.shuizilong.com/house/archives/hdu-5306-gorgeous-sequence/ Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 440    Accepted Submission(s): 87 Problem Description Th

hdu 5306 Gorgeous Sequence(区间最值更新+求和)

题目链接:hdu 5306 Gorgeous Sequence 题意: 给你一个序列,有三种操作. 0 x y t:将[x,y]的数取min(a[i],t) 1 x y:求[x,y]的最大值 2 x y:求[x,y]的区间和 题解: 吉老师的课件题:传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt

hdu 5306 Gorgeous Sequence(暴力线段树)(好题)

题意:区间最大长度为1000000, 三种操作: 区间求和: 区间求最大值: 将节点值更新为当前值与给定值中的最小值(有趣的更新): 思路: 暴力线段树.关键在于处理标记,需要维护最大标记,标记覆盖范围,所在区间: 覆盖区域标记起到很关键的作用: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node{ long long sum; int tag,m

【模板】吉司机线段树 HDU 5306 Gorgeous Sequence

也叫小清新线段树,用于解决区间最值修改问题 具体可以参考jiry_2神犇的集训队论文和WC2016上的PPT 此题就作为模板好了,模板的话写法是比较精妙的 #include<bits/stdc++.h> using namespace std; #define go(i,a,b) for(int i=a;i<=b;++i) #define com(i,a,b) for(int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a))

HDU 5306 Gorgeous Sequence

参考 关键是加一个标记cv:这个区间有多少个结点,已被 tag 影响. Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 396    Accepted Submission(s): 78 Problem Description There is a sequence a of length n.

【hdu5306】Gorgeous Sequence 线段树区间最值操作

题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y$ :求 $[x,y]$ 内所有数的和. 多组测试数据,$\sum n,\sum m\le 10^6$ 题解 线段树区间最值操作 对于线段树上的一个节点,维护对应区间的:最大值 $mx$ .最大值个数 $c$ 及严格次大值 $se$ .那么对于一次区间最小值操作: 如果 $t\ge mx$ ,则这个

HDU 5306 吉司机线段树

思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; const int N=1000050; int cases,n,m,op,xx,yy,zz; typedef long long ll; struct SegTree{int max1,max2,maxnum,lazy;ll s

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor