HDU 5316 Magician (线段树区间最值,单点更新)

题目链接:Magician

题面:

Magician

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1911    Accepted Submission(s): 549

Problem Description

Fantasy magicians usually gain their ability through one of three usual methods: possessing it as an innate talent, gaining it through study and practice, or receiving it from another being, often a god, spirit, or demon of some sort.
Some wizards are depicted as having a special gift which sets them apart from the vast majority of characters in fantasy worlds who are unable to learn magic.

Magicians, sorcerers, wizards, magi, and practitioners of magic by other titles have appeared in myths, folktales, and literature throughout recorded history, with fantasy works drawing from this background.

In medieval chivalric romance, the wizard often appears as a wise old man and acts as a mentor, with Merlin from the King Arthur stories representing a prime example. Other magicians can appear as villains, hostile to the hero.

Mr. Zstu is a magician, he has many elves like dobby, each of which has a magic power (maybe negative). One day, Mr. Zstu want to test his ability of doing some magic. He made the elves stand in a straight line, from position 1 to position n, and he used two
kinds of magic, Change magic and Query Magic, the first is to change an elf’s power, the second is get the maximum sum of beautiful subsequence of a given interval. A beautiful subsequence is a subsequence that all the adjacent pairs of elves in the sequence
have a different parity of position. Can you do the same thing as Mr. Zstu ?

Input

The first line is an integer T represent the number of test cases.

Each of the test case begins with two integers n, m represent the number of elves and the number of time that Mr. Zstu used his magic.

(n,m <= 100000)

The next line has n integers represent elves’ magic power, magic power is between -1000000000 and 1000000000.

Followed m lines, each line has three integers like

type a b describe a magic.

If type equals 0, you should output the maximum sum of beautiful subsequence of interval [a,b].(1 <= a <= b <= n)

If type equals 1, you should change the magic power of the elf at position a to b.(1 <= a <= n, 1 <= b <= 1e9)

Output

For each 0 type query, output the corresponding answer.

Sample Input

1
1 1
1
0 1 1

Sample Output

1

Author

ZSTU

Source

2015 Multi-University Training Contest 3

解题:

算是比较基础的线段树吧,需要维护的值为,区间不同奇偶性起止的数列的最大值。慢慢练吧,还不是很熟练。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 1e9
#define minn -1e18
#define LL long long
using namespace std;
//节点分别存储其左边界,右边界,奇偶/偶偶/偶奇/奇奇最大值
struct node
{
	int l,r;
	LL OE,EE,EO,OO;
}Maxn[400010];
int p,v;
//存储原数据
LL store[100010];
LL max(LL a,LL b)
{
	return a>b?a:b;
}
LL min(LL a,LL b)
{
	return a<b?a:b;
}
//向上更新
void Pushup(int k)
{
	//每个点的值分别为左下区间的相应最值和右下区间最值相加的最大值
	Maxn[k].EO=max(minn,max(Maxn[k<<1].EO+Maxn[(k<<1)+1].EO,Maxn[k<<1].EE+Maxn[(k<<1)+1].OO));
	Maxn[k].EO=max(Maxn[k].EO,Maxn[k<<1].EO);
	Maxn[k].EO=max(Maxn[k].EO,Maxn[(k<<1)+1].EO);

	Maxn[k].OE=max(minn,max(Maxn[k<<1].OE+Maxn[(k<<1)+1].OE,Maxn[k<<1].OO+Maxn[(k<<1)+1].EE));
	Maxn[k].OE=max(Maxn[k].OE,Maxn[k<<1].OE);
	Maxn[k].OE=max(Maxn[k].OE,Maxn[(k<<1)+1].OE);

	Maxn[k].EE=max(minn,max(Maxn[k<<1].EO+Maxn[(k<<1)+1].EE,Maxn[k<<1].EE+Maxn[(k<<1)+1].OE));
	Maxn[k].EE=max(Maxn[k].EE,Maxn[k<<1].EE);
	Maxn[k].EE=max(Maxn[k].EE,Maxn[(k<<1)+1].EE);

    Maxn[k].OO=max(minn,max(Maxn[k<<1].OE+Maxn[(k<<1)+1].OO,Maxn[k<<1].OO+Maxn[(k<<1)+1].EO));
	Maxn[k].OO=max(Maxn[k].OO,Maxn[k<<1].OO);
	Maxn[k].OO=max(Maxn[k].OO,Maxn[(k<<1)+1].OO);

}
//建树
void build(int l,int r,int k)
{
	int M;
	Maxn[k].l=l;
	Maxn[k].r=r;
	//为叶子节点
	if(l==r)
	{
		//该位置为奇
		if(l%2)
		{
			Maxn[k].OO=store[l];
			Maxn[k].OE=Maxn[k].EE=Maxn[k].EO=minn;
		}
		else
		{
			Maxn[k].EE=store[l];
			Maxn[k].OE=Maxn[k].EO=Maxn[k].OO=minn;
		}
		return;
	}
	//分别向左下区间,和右下区间建树
	M=(l+r)>>1;
	build(l,M,k<<1);
	build(M+1,r,(k<<1)+1);
	//初始化区间最值
	Pushup(k);
}
//询问
node query(int l,int r,int k)
{
    node temp,t1,t2;
    int M;
	//刚好为该区间,返回该区间最值
    if (Maxn[k].l==l && Maxn[k].r==r)
        return Maxn[k];
	//否则取该节点对应的中点,细分
    M=(Maxn[k].l+Maxn[k].r)>>1;
	//完全包含在左区间
    if (r<=M) return query(l,r,k<<1);
	//完全包含在右区间
    else  if (l>M) return query(l,r,(k<<1)+1);
	//落在左区间和右区间,取两边相加的最大值
    else
    {
        t1=query(l,M,k<<1);
        t2=query(M+1,r,(k<<1)+1);
        temp.EE=max(max(max(t1.EE+t2.OE,t1.EO+t2.EE),t1.EE),t2.EE);
        temp.EO=max(max(max(t1.EO+t2.EO,t1.EE+t2.OO),t1.EO),t2.EO);
        temp.OO=max(max(max(t1.OO+t2.EO,t1.OE+t2.OO),t1.OO),t2.OO);
        temp.OE=max(max(max(t1.OO+t2.EE,t1.OE+t2.OE),t1.OE),t2.OE);
        return temp;
    }
}
//更新操作
void update(int o,int L,int R)
{
  int M=L+(R-L)/2;
  //叶子节点
  if(L==R)
  {
	  if(L%2)
		  Maxn[o].OO=v;
	  else
		  Maxn[o].EE=v;
	  return;
  }
  //继续细分
  else
  {
	  if(p<=M)
		  update(o*2,L,M);
	  else
		  update(o*2+1,M+1,R);
	  //维护区间最值
      Pushup(o);
  }
}
int main()
{
    int t,n,m,a,oper;
	scanf("%d",&t);
	while(t--)
	{
		//读入
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%lld",&store[i]);
		build(1,n,1);
		for(int i=0;i<m;i++)
		{
           scanf("%d%d%d",&oper,&a,&v);
		   //查询操作
		   if(oper==0)
		   {
			   node temp=query(a,v,1);
               LL ans=minn;
			   ans=max(ans,temp.OO);
			   ans=max(ans,temp.OE);
			   ans=max(ans,temp.EE);
			   ans=max(ans,temp.EO);
			   printf("%lld\n",ans);
		   }
		   //更新操作,v设置为全局了
		   else
		   {
               p=a;
			   update(1,1,n);
		   }
		}
	}
	return 0;
}

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

时间: 2024-10-25 20:25:46

HDU 5316 Magician (线段树区间最值,单点更新)的相关文章

HDU 5316 Magician(线段树区间合并, 子序列最值 多校2015啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 Problem Description Fantasy magicians usually gain their ability through one of three usual methods: possessing it as an innate talent, gaining it through study and practice, or receiving it from an

51nod1287(二分/线段树区间最值&amp;单点更新)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1287 题意:中文题诶- 解法1:b[i] 存储 max(a[0], ....., a[i]),显然 b 是单调不减的,所以直接二分 x,再更新 a 和 b 数组即可: 代码: 1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 const int MAXN =

hdu 5316 Magician (线段树)

题目链接: hdu 5316 Magician 题目描述: 有n个精灵,每个精灵都有一个魔法值,现在有两个操作: (0, a, b)查询[a, b]序列中的一个完美序列的最大和,完美序列就是数组中相邻数字的下标奇偶性不同. (1, a, b)更新下标为a的精灵魔法值为b. 对的,没错就是这个意思,但是比赛的时候就是题意卡的死死的有没有啊,就是各种不懂有没有啊!!! 1 #include <cstdio> 2 #include <cstring> 3 #include <ios

HDU 1754(线段树区间最值)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 48513    Accepted Submission(s): 18986 Problem Description 非常多学校流行一种比較的习惯.老师们非常喜欢询问.从某某到某某其中,分数最高的是多少. 这让非常多学生非常反感. 无论你喜不喜欢,如今须要你做的是,就是

(线段树 区间最大,单点更新) I Hate It

B - I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. Input 本题目包含多组测试,请处

【POJ】3264 Balanced Lineup ——线段树 区间最值

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 34140   Accepted: 16044 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

【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$ ,则这个

hdu5316 Magician(线段树区间合并)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:有n个精灵,每个精灵有一个能力值,有两种操作①改变某一个精灵的能力值②查询区间[L,R]里面位置奇偶相间的能力值的最大和. 分析:这题线段树区间合并可以做.每个节点保存4个信息:①以奇位置开始偶位置结束的奇偶序列最大和②以奇位置开始奇位置结束的奇偶序列最大和③以偶位置开始偶位置结束的奇偶序列最大和④以偶位置开始奇位置结束的奇偶序列最大和 合并的时候,以奇位置开始偶位置结束的奇偶序列最大和=m

HDU 3308 LCIS (线段树区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1

HDU 1754 I Hate It&lt;区间最值 单点修改&gt;

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 76334    Accepted Submission(s): 29413 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要