hdu 5316 线段树

因为题目要求子序列中相邻元素下标的奇偶性不同所以线段树中需要维护4个值:jj,jo,oj,oo分别代表奇数开头和结尾、奇数开头偶数结尾、偶数开头奇数结尾和偶数开头和结尾的子序列的和的最大值,然后就是普通的单点修改和区间查询了。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5
  6 typedef long long ll;
  7 const ll INF = 100000000000000000;
  8 const int N = 100010;
  9 ll a[N];
 10
 11 struct Node
 12 {
 13     int l, r;
 14     ll jj, jo, oj, oo;
 15 } node[N << 2];
 16
 17 ll max( ll x, ll y )
 18 {
 19     return x > y ? x : y;
 20 }
 21
 22 void pushup( int i )
 23 {
 24     int lc = i << 1, rc = lc | 1;
 25     node[i].jj = max( node[lc].jj, node[rc].jj );
 26     node[i].jj = max( node[i].jj, node[lc].jj + node[rc].oj );
 27     node[i].jj = max( node[i].jj, node[lc].jo + node[rc].jj );
 28     node[i].jo = max( node[lc].jo, node[rc].jo );
 29     node[i].jo = max( node[i].jo, node[lc].jo + node[rc].jo );
 30     node[i].jo = max( node[i].jo, node[lc].jj + node[rc].oo );
 31     node[i].oj = max( node[lc].oj, node[rc].oj );
 32     node[i].oj = max( node[i].oj, node[lc].oj + node[rc].oj );
 33     node[i].oj = max( node[i].oj, node[lc].oo + node[rc].jj );
 34     node[i].oo = max( node[lc].oo, node[rc].oo );
 35     node[i].oo = max( node[i].oo, node[lc].oj + node[rc].oo );
 36     node[i].oo = max( node[i].oo, node[lc].oo + node[rc].jo );
 37 }
 38
 39 void build( int i, int l, int r )
 40 {
 41     node[i].l = l, node[i].r = r;
 42     if ( l == r )
 43     {
 44         if ( l & 1 )
 45         {
 46             node[i].jj = a[l];
 47             node[i].jo = node[i].oj = node[i].oo = -INF;
 48         }
 49         else
 50         {
 51             node[i].oo = a[l];
 52             node[i].jj = node[i].jo = node[i].oj = -INF;
 53         }
 54         return ;
 55     }
 56     int mid = ( l + r ) >> 1;
 57     build( i << 1, l, mid );
 58     build( i << 1 | 1, mid + 1, r );
 59     pushup(i);
 60 }
 61
 62 void update( int i, int pos, int val )
 63 {
 64     if ( node[i].l == pos && node[i].r == pos )
 65     {
 66         if ( pos & 1 )
 67         {
 68             node[i].jj = val;
 69         }
 70         else
 71         {
 72             node[i].oo = val;
 73         }
 74         return ;
 75     }
 76     int mid = ( node[i].l + node[i].r ) >> 1;
 77     if ( pos <= mid )
 78     {
 79         update( i << 1, pos, val );
 80     }
 81     else
 82     {
 83            update( i << 1 | 1, pos, val );
 84     }
 85     pushup(i);
 86 }
 87
 88 Node query( int i, int l, int r )
 89 {
 90     if ( node[i].l == l && node[i].r == r ) return node[i];
 91     int lc = i << 1, rc = lc | 1, mid = ( node[i].l + node[i].r ) >> 1;
 92     if ( r <= mid )
 93     {
 94         return query( lc, l, r );
 95     }
 96     else if ( l > mid )
 97     {
 98         return query( rc, l, r );
 99     }
100     else
101     {
102         Node ln = query( lc, l, mid ), rn = query( rc, mid + 1, r ), res;
103         res.jj = max( ln.jj, rn.jj );
104         res.jj = max( res.jj, ln.jj + rn.oj );
105         res.jj = max( res.jj, ln.jo + rn.jj );
106         res.jo = max( ln.jo, rn.jo );
107         res.jo = max( res.jo, ln.jj + rn.oo );
108         res.jo = max( res.jo, ln.jo + rn.jo );
109         res.oj = max( ln.oj, rn.oj );
110         res.oj = max( res.oj, ln.oj + rn.oj );
111         res.oj = max( res.oj, ln.oo + rn.jj );
112         res.oo = max( ln.oo, rn.oo );
113         res.oo = max( res.oo, ln.oo + rn.jo );
114         res.oo = max( res.oo, ln.oj + rn.oo );
115         return res;
116     }
117 }
118
119 int main()
120 {
121     int t;
122     scanf("%d", &t);
123     while ( t-- )
124     {
125         int n, m;
126         scanf("%d%d", &n, &m);
127         for ( int i = 1; i <= n; i++ )
128         {
129             scanf("%I64d", &a[i]);
130         }
131         build( 1, 1, n );
132         while ( m-- )
133         {
134             int op;
135             scanf("%d", &op);
136             if ( op == 0 )
137             {
138                 int l, r;
139                 scanf("%d%d", &l, &r);
140                 Node nn = query( 1, l, r );
141                 ll ans = nn.jj;
142                 ans = max( ans, nn.jo );
143                 ans = max( ans, nn.oj );
144                 ans = max( ans, nn.oo );
145                 printf("%I64d\n", ans);
146             }
147             else if ( op == 1 )
148             {
149                 int pos, val;
150                 scanf("%d%d", &pos, &val);
151                 update( 1, pos, val );
152             }
153         }
154     }
155     return 0;
156 }
时间: 2024-08-26 09:11:10

hdu 5316 线段树的相关文章

HDU 5316 线段树区间最值问题

T组数据 N个数字,M次操作 op=0:找出L-R区间内的最大'值' op=1:把a位置的数字换成b 对最大'值'的定义:取区间内的最大子序列,需要保证子序列的下标为奇偶交替的 用线段树分别记录每个区间的 ee:以偶数下标开始偶数下标结束的最大和 eo:以偶数下标开始奇数下标结束的最大和 oe:以奇数下标开始偶数下标结束的最大和 oo:以奇数下标开始奇数下标结束的最大和 对每次询问分别处理4种情况的最大值即可 修改时单点更新即可 #include "stdio.h" #include

HDU 4893 线段树裸题

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

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在

hdu 2795 线段树--点更新

http://acm.hdu.edu.cn/showproblem.php?pid=2795 多校的第一场和第三场都出现了线段树,比赛期间没做,,这两天先做几道热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题 关键是建模: 首先一定看清楚题目构造的场景,看有什么特点--------会发现,如果尽量往左上放置的话,那么由于 the i-th announcement is a rectangle of size 1 * wi.,完全可以对h建立线段树,表示一行,结点里的l,r就表示

HDU 1698 线段树(区间染色)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16255    Accepted Submission(s): 8089 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f