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

There is a sequence a of
length n.
We use ai to
denote the i-th
element in this sequence. You should do the following three types of operations to this sequence.

0 x y t:
For every x≤i≤y,
we use min(ai,t) to
replace the original ai‘s
value.

1 x y:
Print the maximum value of ai that x≤i≤y.

2 x y:
Print the sum of ai that x≤i≤y.

Input

The first line of the input is a single integer T,
indicating the number of testcases.

The first line contains two integers n and m denoting
the length of the sequence and the number of operations.

The second line contains n separated
integers a1,…,an (?1≤i≤n,0≤ai<231).

Each of the following m lines
represents one operation (1≤x≤y≤n,0≤t<231).

It is guaranteed that T=100, ∑n≤1000000, ∑m≤1000000.

Output

For every operation of type 1 or 2,
print one line containing the answer to the corresponding query.

Sample Input

1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5

Sample Output

5
15
3
12

Hint

Please use efficient IO method

Source

field=problem&key=2015+Multi-University+Training+Contest+2&source=1&searchmode=source" style="color:rgb(26,92,200); text-decoration:none">2015 Multi-University Training Contest 2

/* ***********************************************
Author        :CKboss
Created Time  :2015年07月27日 星期一 08时13分39秒
File Name     :HDOJ5306.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const int maxn=1000030;

int n,m;
int a[maxn];

struct Node
{
	LL ss;
	int mx,tag,cv;

	void toString() {
		printf("ss: %lld mx: %d tag: %d cv: %d\n",ss,mx,tag,cv);
	}

}T[maxn<<2];

#define lrt (rt<<1)
#define rrt (rt<<1|1)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

void push_up(int rt)
{
	T[rt].ss=T[lrt].ss+T[rrt].ss;
	T[rt].mx=max(T[lrt].mx,T[rrt].mx);
	T[rt].cv=T[lrt].cv+T[rrt].cv;
}

void pnc(int t,int l,int r,int rt)
{
	if(T[rt].tag!=0&&T[rt].tag<=t) return ;

	int all=r-l+1;
	if(T[rt].cv!=all)
	{
		T[rt].ss+=(LL)t*(all-T[rt].cv);
		T[rt].tag=T[rt].mx=t;
		T[rt].cv=all;
	}
}

void push_down(int l,int r,int rt)
{
	if(T[rt].tag)
	{
		int m=(l+r)/2;
		pnc(T[rt].tag,lson); pnc(T[rt].tag,rson);
	}
}

/// 清除掉全部大于t的标记
void fix(int t,int l,int r,int rt)
{
	if(T[rt].mx<t) return ;

	if(T[rt].tag>=t) T[rt].tag=0;
	if(l==r)
	{
		T[rt].ss=T[rt].mx=T[rt].tag;
		T[rt].cv=T[rt].tag!=0;
	}
	else
	{
		push_down(l,r,rt);
		int m=(l+r)/2;
		fix(t,lson); fix(t,rson);
		push_up(rt);
	}
}

void build(int l,int r,int rt)
{
	if(l==r)
	{
		T[rt].ss=T[rt].mx=T[rt].tag=a[l];
		T[rt].cv=1;
		return ;
	}

	T[rt].tag=0;
	int m=(l+r)/2;
	build(lson); build(rson);
	push_up(rt);
}

/// 0
void update(int L,int R,int t,int l,int r,int rt)
{
	if(T[rt].mx<=t) return ;

	if(L<=l&&r<=R)
	{
		fix(t,l,r,rt);
		if(l==r)
		{
			T[rt].ss=T[rt].mx=T[rt].tag=t;
			T[rt].cv=1;
		}
		else push_up(rt);

		pnc(t,l,r,rt);
	}
	else
	{
		push_down(l,r,rt);
		int m=(l+r)/2;
		if(L<=m) update(L,R,t,lson);
		if(R>m) update(L,R,t,rson);
		push_up(rt);
	}
}

/// 1
int query_max(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R) return T[rt].mx;

	push_down(l,r,rt);

	int m=(l+r)/2;
	int ret=0;

	if(L<=m) ret=max(ret,query_max(L,R,lson));
	if(R>m) ret=max(ret,query_max(L,R,rson));

	return ret;
}

/// 2
LL query_sum(int L,int R,int l,int r,int rt)
{
	if(L<=l&&r<=R) return T[rt].ss;

	push_down(l,r,rt);

	int m=(l+r)/2;

	LL ret=0;
	if(L<=m) ret+=query_sum(L,R,lson);
	if(R>m) ret+=query_sum(L,R,rson);

	return ret;
}

void show(int l,int r,int rt)
{
	printf("rt: %d %d <---> %d\n   ",rt,l,r);
	T[rt].toString();

	if(l==r) return ;

	int m=(l+r)/2;
	show(lson); show(rson);
}

/********** fast read **************/

char *ch,buf[40*1024000+5];

void nextInt(int& x)
{
	x=0;
	for(++ch;*ch<=32;++ch);
	for(x=0;'0'<=*ch;ch++) x=x*10+*ch-'0';
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

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

	int T_T;
	nextInt(T_T);

	while(T_T--)
	{
		nextInt(n); nextInt(m);

		for(int i=1;i<=n;i++) nextInt(a[i]);

		build(1,n,1);

		int k,l,r,t;
		while(m--)
		{
			nextInt(k);
			if(k==0)
			{
				nextInt(l); nextInt(r); nextInt(t);
				update(l,r,t,1,n,1);
			}
			else if(k==1)
			{
				nextInt(l); nextInt(r);
				printf("%d\n",query_max(l,r,1,n,1));
			}
			else if(k==2)
			{
				nextInt(l); nextInt(r);
				//printf("%lld\n",query_sum(l,r,1,n,1));
				printf("%I64d\n",query_sum(l,r,1,n,1));
			}
		}
	}
    return 0;
}
时间: 2024-10-12 06:51:24

HDOJ 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

【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 Gorgeous Sequence(线段树)

题目链接:hdu 5306 Gorgeous Sequence 和普通的线段树一样一个标记值T,然后另外加一个C值记录以u为根节点的子树下有多少个叶子节点被T值控制.每次修改时,dfs到叶子节点之后在修改该节点.维护sum值时只要额外加上T值控制下的节点.加了个输入外挂,时间少了将近1000ms. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const in

HDOJ 4893 Wow! Such Sequence! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和. 分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少.开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum. 1 #include<cstdio> 2 #include<cstring>

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

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

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

HDU4893 Wow! Such Sequence! 线段树

题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得出,为节点维护两个 和,一个是 斐波纳契和 一个是正常和 ,再看这个区间有没有被3覆盖,特判一下就行了. 解题代码: 1 // File Name: 1007.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 12时49分33

hdu-4893-Wow! Such Sequence!-线段树【2014多校第三场-J】

题意:一个初始为0的数组,支持三种操作:1.向第k个数添加d,(|d| < 2^31);2.把[l, r]区间内的数字都换成与它最相近的Fibonacci数;3.询问[l, r]区间的和. 思路:初始化Fibonacci数组,longlong 类型内90个就够用了. 线段树区间查询,用lazy标记, sgt[]记录线段树各个节点的区间和, fib_num_sum[]记录与各个叶子节点当前值最接近的Fibonacci数,传递到区间fib_num_sum[]就是区间Fibonacci数的和. 操作1