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 <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 typedef long long LL;
  7 #define Max(a, b, c, d) max(max(a, b), max(c, d))
  8 const LL INF = 1000000000;
  9 const LL maxn = 400000;
 10 struct point
 11 {
 12     LL odd_e, odd_o, even_o, even_e;
 13     LL Maxn ()
 14     {
 15         return Max(odd_e, odd_o, even_e, even_o);
 16     }
 17 };
 18 struct node
 19 {
 20     LL l, r;
 21     point p;
 22     LL Mid ()
 23     {
 24         return (l+r)/2;
 25     }
 26 } tree[maxn];
 27 point Add (point x, point y)
 28 {
 29     point s;
 30     s.even_e = Max(x.even_e, y.even_e, x.even_e+y.odd_e,  x.even_o+y.even_e);
 31     s.even_o = Max(x.even_o, y.even_o, x.even_e+y.odd_o,  x.even_o+y.even_o);
 32     s.odd_e  = Max(x.odd_e,  y.odd_e,  x.odd_e +y.odd_e,  x.odd_o+y.even_e);
 33     s.odd_o  = Max(x.odd_o,  y.odd_o,  x.odd_o +y.even_o, x.odd_e+y.odd_o);
 34     return s;
 35 }
 36 void bulid (LL root, LL l, LL r)
 37 {
 38     tree[root].l = l;
 39     tree[root].r = r;
 40
 41     if (l == r)
 42     {
 43         tree[root].p.even_e = -INF;
 44         tree[root].p.even_o = -INF;
 45         tree[root].p.odd_e = -INF;
 46         tree[root].p.odd_o = -INF;
 47         LL num;
 48         scanf ("%lld", &num);
 49         if (l%2)
 50             tree[root].p.odd_o = num;
 51         else
 52             tree[root].p.even_e = num;
 53         return ;
 54     }
 55     bulid (2*root+1, l, tree[root].Mid());
 56     bulid (2*root+2, tree[root].Mid()+1, r);
 57     tree[root].p = Add (tree[2*root+1].p, tree[2*root+2].p);
 58 }
 59 void update (LL root, LL x, LL y)
 60 {
 61     if (tree[root].l == tree[root].r)
 62     {
 63         tree[root].p.even_e = -INF;
 64         tree[root].p.even_o = -INF;
 65         tree[root].p.odd_e = -INF;
 66         tree[root].p.odd_o = -INF;
 67         if ( x%2 == 0 )
 68             tree[root].p.even_e = y;
 69         else
 70             tree[root].p.odd_o = y;
 71         return ;
 72     }
 73     if (x <= tree[root].Mid())
 74         update(2*root+1, x, y);
 75     else
 76         update(2*root+2, x, y);
 77     tree[root].p = Add (tree[2*root+1].p, tree[2*root+2].p);
 78 }
 79 point query (LL root, LL l, LL r)
 80 {
 81     if (tree[root].l == l && tree[root].r == r)
 82         return tree[root].p;
 83     if (r <= tree[root].Mid())
 84         query (2*root+1, l, r);
 85     else if (tree[root].Mid() < l)
 86         query (2*root+2, l, r);
 87     else
 88     {
 89         point ls, rs;
 90         ls = query (2*root+1, l, tree[root].Mid());
 91         rs = query (2*root+2, tree[root].Mid()+1, r);
 92         return Add (ls, rs);
 93     }
 94 }
 95 int main ()
 96 {
 97     LL t;
 98     scanf ("%lld", &t);
 99
100     while (t --)
101     {
102         LL n, q;
103         scanf ("%lld %lld", &n, &q);
104         bulid(0, 1, n);
105         while (q --)
106         {
107             LL type, a, b;
108             scanf ("%lld %lld %lld", &type, &a, &b);
109             if (type == 0)
110             {
111                 point s = query (0, a, b);
112                 printf ("%lld\n", s.Maxn());
113             }
114             else
115                 update (0, a, b);
116         }
117     }
118     return 0;
119 }
时间: 2024-10-23 03:50:16

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

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 1828 Picture(线段树&amp;扫描线&amp;周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2578    Accepted Submission(s): 1363 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

hdu 1542 Atlantis(线段树)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6899    Accepted Submission(s): 3022 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 4864(2) 线段树

对task和machine的yi由小到大进行排序,然后对machine来跟task配对.当machine[].yi >= task[].yi时,就更新线段树,在1-1440上做线段树,线段树存的是task[].xi,同时用用优先队列保存task[].yi:当machine[].yi < task[].yi时,就查找 1到machine[].xi最大的值.如果存在最大值的话,把优先队列里的task[].yi取出来..这样一个machine就匹配到了一个最优的任务.还是看代码好好意会吧,细节挺多的