解题报告 之 HDU5316 Magician
来源:互联网 发布:刺客信条3低配优化 编辑:程序博客网 时间:2024/04/29 15:49
解题报告 之 HDU5316 Magician
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 ?
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.
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)
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
11 110 1 1
Sample Output
1
题目大意:给出一个n个数字的序列,有两种操作。第一种操作是将某位置的数字改变为新的数字,第二种操作是问某范围内美丽子序列的最大和。所谓美丽子序列,就是指按顺序选出一些数,这些数中任意相邻的两个数的原位置编号必须一奇一偶。
分析:首先吐槽一下没有用的三段阅读理解以及一张诡异的图片。作为资深小白,看到这种各种操作的就只会想到线段树(毕竟数据结构不是我负责,囧)。那么问题的核心就在于节点要维护什么信息,经过思考之后一开始认为可以直接维护该区间的美丽子序列最大和,但是发现并不行,因为可能两个节点加在一起会出现与原来不同的美丽子序列(比如节点 i 的最大美丽子序列是 奇偶奇偶奇偶奇 ,j 的最大美丽子序列是奇偶奇偶奇偶,但这两个美丽子序列并不能直接相连。 可能 i 和 j 合并以后有更大的美丽子序列 奇偶奇偶奇偶奇偶奇偶奇偶)。
针对上面的问题,我们需要维护四个信息,就是以 奇/偶 开头 以 奇/偶 结尾的最大美丽子序列的和。然后剩下的工作就是裸的线段树了。
上代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>typedef long long ll;using namespace std;struct Node{int ex[2][2];//exist 表示是否该区间是否存在以 奇/偶 开头/结尾的最大美丽子序列ll M[2][2]; //0表示奇,1表示偶数,M[0][1]表示该区间内以奇开头,以偶结尾的最大美丽子序列和}node[100000 * 4];Node conj( Node a, Node b ){Node c;for(int i = 0; i <= 1; i++)for(int j = 0; j <= 1; j++) //首先合并之后的区间可以直接以a、b区间的最大和作为最大和{c.ex[i][j] = a.ex[i][j] | b.ex[i][j];if(a.ex[i][j] && b.ex[i][j])c.M[i][j] = max( a.M[i][j], b.M[i][j] );else if(a.ex[i][j])c.M[i][j] = a.M[i][j];else if(b.ex[i][j])c.M[i][j] = b.M[i][j];}for(int i = 0; i <= 1; i++) //当然也有可能将两个区间的某个子序列合并起来for(int j = 0; j <= 1; j++)for(int k = 0; k <= 1; k++)if(a.ex[i][j] && b.ex[!j][k])if(c.ex[i][k])c.M[i][k] = max( c.M[i][k], a.M[i][j] + b.M[!j][k] );elsec.ex[i][k] = 1, c.M[i][k] = a.M[i][j] + b.M[!j][k];return c;}void build( int root, int l, int r ){memset( node[root].ex, 0, sizeof( node[root].ex ) );if(l == r){int a;scanf( "%d", &a );node[root].ex[l % 2][l % 2] = 1;node[root].M[l % 2][l % 2] = a;return;}int mid = (l + r) / 2;build( root * 2, l, mid );build( root * 2 + 1, mid + 1, r );node[root] = conj( node[root * 2], node[root * 2 + 1] );}void update( int root, int l, int r, int x, int y ){if(l == r){memset( node[root].ex, 0, sizeof( node[root].ex ) );node[root].ex[l % 2][l % 2] = 1;node[root].M[l % 2][l % 2] = y;return;}int mid = (l + r) / 2;if(x <= mid)update( root * 2, l, mid, x, y );elseupdate( root * 2 + 1, mid + 1, r, x, y );node[root] = conj( node[root * 2], node[root * 2 + 1] ); //更新完成后一路上的节点都要重新连接一下}Node query( int root, int l, int r, int x, int y )//找到并制作成要求的区间再返回{if(x <= l&&y >= r)return node[root];int flag1 = 0, flag2 = 0;Node x1, x2;int mid = (l + r) / 2;if(x <= mid)x1 = query( root * 2, l, mid, x, y ), flag1 = 1;if(y>mid)x2 = query( root * 2 + 1, mid + 1, r, x, y ), flag2 = 1;if(flag1 == 0)return x2;if(flag2 == 0)return x1;return conj( x1, x2 );}int main(){int T;cin >> T;while(T--){int n, m;cin >> n >> m;build( 1, 1, n );for(int i = 1; i <= m; i++){int x, y, z;scanf( "%d%d%d", &x, &y, &z );if(x == 0){Node t = query( 1, 1, n, y, z );ll ans;int flag = 0;for(int i = 0; i <= 1; i++)for(int j = 0; j <= 1; j++)if(t.ex[i][j])if(flag == 0)ans = t.M[i][j], flag = 1;elseans = max( ans, t.M[i][j] );cout << ans << endl;}elseupdate( 1, 1, n, y, z );}}return 0;}
0 0
- 解题报告 之 HDU5316 Magician
- HDU5316-Magician
- HDU5316.Magician(多校)
- HDU5316 Magician 线段树区间合并
- hdu5316 Magician(线段树区间合并)
- HDU5316 Magician (线段树区间合并)
- hdu5316 Magician(线段树区间合并)
- hdu5316 Magician(15多校第三场1001)(线段树)
- hdu5316(2015多校3)--Magician(线段树+dp)
- hdu5316 Magician (线段树+单点更新+区间查询+区间合并)
- hdu5316
- 解题报告之DisjointSet
- 解题报告之 非诚勿扰
- Nightmare之BFS解题报告
- Asteroids之BFS解题报告
- 解题报告之 字频统计
- 解题报告之 幸运数字
- 解题报告 之 UVA1347 Tour
- 详解Hibernate Session & Transaction
- 黑马程序员--Java基础学习(IO流)第十九天
- 数据库常用高级用法(不定期更新)
- Ubuntu 安装keepalived
- UILable
- 解题报告 之 HDU5316 Magician
- hdu 5418 Victor and World(floyd+状压dp)
- 黑马程序员-[OC]学习之旅-ARC机制和类别
- ASP.NET MVC 4 插件化架构简单实现-思路篇
- jQeury入门:jQuery对象
- 每个Android开发者应该知道的6个SDK和API
- addChildViewController的用法
- Vim 编解器常用命令总结
- 常用的日文正文字体有哪些?