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<<1|1
 5 using namespace std;
 6 typedef long long ll;
 7 const int N=4e6+7;
 8
 9 int t,n,m,mx[N],se[N],num[N];
10 ll sum[N];
11
12 inline void dec_tag(int rt,int val)
13 {
14     if(val>=mx[rt])return;
15     sum[rt]-=1ll*(mx[rt]-val)*num[rt],mx[rt]=val;
16 }
17
18 inline void PD(int rt){dec_tag(rt<<1,mx[rt]),dec_tag(rt<<1|1,mx[rt]);}
19
20 inline void PU(int rt)
21 {
22     int l=rt<<1,r=rt<<1|1;
23     sum[rt]=sum[l]+sum[r],num[rt]=0;
24     mx[rt]=max(mx[l],mx[r]);
25     se[rt]=max(max(se[l],se[r]),mx[l]==mx[r]?0:min(mx[l],mx[r]));
26     if(mx[rt]==mx[l])num[rt]+=num[l];
27     if(mx[rt]==mx[r])num[rt]+=num[r];
28 }
29
30 void build(int l=1,int r=n,int rt=1)
31 {
32     se[rt]=-1;
33     if(l==r)
34     {
35         int x;
36         scanf("%d",&x);
37         sum[rt]=mx[rt]=x,num[rt]=1;
38         return;
39     }
40     int m=l+r>>1;
41     build(ls),build(rs);
42     PU(rt);
43 }
44
45 void update(int L,int R,int val,int l=1,int r=n,int rt=1)
46 {
47     if(val>=mx[rt])return;
48     if(L<=l&&r<=R&&val>se[rt]){dec_tag(rt,val);return;}
49     PD(rt);
50     int m=l+r>>1;
51     if(L<=m)update(L,R,val,ls);
52     if(R>m)update(L,R,val,rs);
53     PU(rt);
54 }
55
56 ll query(int type,int L,int R,int l=1,int r=n,int rt=1)
57 {
58     if(L<=l&&r<=R){return type==1?mx[rt]:sum[rt];}
59     PD(rt);
60     int m=l+r>>1;ll ans=0;
61     if(L<=m)ans=(type==1?max(ans,query(type,L,R,ls)):ans+query(type,L,R,ls));
62     if(R>m)ans=(type==1?max(ans,query(type,L,R,rs)):ans+query(type,L,R,rs));
63     return ans;
64 }
65
66 int main()
67 {
68     scanf("%d",&t);
69     while(t--)
70     {
71         scanf("%d%d",&n,&m);
72         build();
73         int a,b,c,d;
74         F(i,1,m)
75         {
76             scanf("%d",&a);
77             if(!a)scanf("%d%d%d",&b,&c,&d),update(b,c,d);
78             else scanf("%d%d",&b,&c),printf("%lld\n",query(a,b,c));
79         }
80     }
81     return 0;
82 }

时间: 2024-12-07 15:18:02

hdu 5306 Gorgeous Sequence(区间最值更新+求和)的相关文章

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

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

HDU 5306 Gorgeous Sequence

参考 关键是加一个标记cv:这个区间有多少个结点,已被 tag 影响. Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 396    Accepted Submission(s): 78 Problem Description There is a sequence a of length n.

hdu 5306 Gorgeous Sequence(暴力线段树)(好题)

题意:区间最大长度为1000000, 三种操作: 区间求和: 区间求最大值: 将节点值更新为当前值与给定值中的最小值(有趣的更新): 思路: 暴力线段树.关键在于处理标记,需要维护最大标记,标记覆盖范围,所在区间: 覆盖区域标记起到很关键的作用: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node{ long long sum; int tag,m

【模板】吉司机线段树 HDU 5306 Gorgeous Sequence

也叫小清新线段树,用于解决区间最值修改问题 具体可以参考jiry_2神犇的集训队论文和WC2016上的PPT 此题就作为模板好了,模板的话写法是比较精妙的 #include<bits/stdc++.h> using namespace std; #define go(i,a,b) for(int i=a;i<=b;++i) #define com(i,a,b) for(int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a))

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 Th

HDU 3308 LCIS(区间合并 + 单点更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意:给定n个数.2种操作. 更新第a个数为b. 查询区间[a,b]的最长连续上升子序列. 思路:裸的区间合并.每个结点存 从区间左端点开始的最长连续上升子序列的长度lm. 以区间右端点结束的最长连续上升子序列的长度rm. 区间的最长连续上升子序列的长度mx. 区间左端点的数值la. 区间右端点的数值ra. 代码: #include <iostream> #include <stdio

HDU 5316 线段树区间最值问题

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

XTU1238 Segment Tree (线段树&#183;区间最值更新)

对一个数组有四种操作 1: 将区间[ l, r] 中的所有值都加上c 2:将区间 [l, r] 中所有比c大的值改为c 3:将区间 [l, r] 中所有比c小的值改为c 4:输出区间 [l, r] 中所有数的最小值和最大值 对每个操作4输出对应最小值和最大值基础的线段树  在湘潭卡了好久没写出来  线段树维护三个值 区间最大值 maxv, 区间最小值minv, 区间增加的值add  操作1是... http://www.worlduc.com/blog2012.aspx?bid=44692767