2015 Multi-University Training Contest 2 hdu 5306 Gorgeous Sequence
Gorgeous Sequence
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 349 Accepted Submission(s): 57
0 x y t: For every x≤i≤y, we use min(ai,t) to replace the original ai's value.
1 x y: Print the maximum value of ai that x≤i≤y.
2 x y: Print the sum of ai that x≤i≤y.
Each of the following m lines represents one operation (1≤x≤y≤n,0≤t<231).
It is guaranteed that T=100, ∑n≤1000000, ∑m≤1000000.
Please use efficient IO method
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long LL;
- const int maxn = ;
- struct node {
- int cover,s,tag,maxtag,maxv;
- LL sum;
- } tree[maxn<<];
- node put(node c,int t) {
- if(!t) return c;
- if(c.cover != c.s) c.maxv = t;
- c.maxtag = t;
- c.sum += (LL)t*(c.s - c.cover);
- c.cover = c.s;
- return c;
- }
- node calc(const node &a,const node &b,int t) {
- node c;
- c.tag = t;
- c.s = a.s + b.s;
- c.sum = a.sum + b.sum;
- c.cover = a.cover + b.cover;
- c.maxv = max(a.maxv,b.maxv);
- c.maxtag = max(a.maxtag,b.maxtag);
- return put(c,t);
- }
- int tmp,n,m;
- void build(int L,int R,int v) {
- tree[v].tag = ;
- tree[v].s = R - L + ;
- if(L == R) {
- scanf("%d",&tmp);
- tree[v].sum = tree[v].tag = tree[v].maxtag = tree[v].maxv = tmp;
- tree[v].cover = ;
- return;
- }
- int mid = (L + R)>>;
- build(L,mid,v<<);
- build(mid+,R,v<<|);
- tree[v] = calc(tree[v<<],tree[v<<|],);
- }
- node query(int L,int R,int lt,int rt,int v) {
- if(lt <= L && rt >= R) return tree[v];
- int mid = (L + R)>>;
- if(rt <= mid) return put(query(L,mid,lt,rt,v<<),tree[v].tag);
- if(lt > mid) return put(query(mid+,R,lt,rt,v<<|),tree[v].tag);
- return calc(query(L,mid,lt,rt,v<<),query(mid+,R,lt,rt,v<<|),tree[v].tag);
- }
- void cleartag(int v,int t) {
- if(tree[v].maxtag < t) return;
- if(tree[v].tag >= t) tree[v].tag = ;
- if(tree[v].s > ) {
- cleartag(v<<,t);
- cleartag(v<<|,t);
- }
- if(tree[v].s == ) {
- tree[v].sum = tree[v].maxtag = tree[v].maxv = tree[v].tag;
- tree[v].cover = (tree[v].tag > );
- } else tree[v] = calc(tree[v<<],tree[v<<|],tree[v].tag);
- }
- void update(int L,int R,int lt,int rt,int t,int v) {
- if(tree[v].tag && tree[v].tag <= t) return;
- if(lt <= L && rt >= R) {
- cleartag(v,t);
- tree[v].tag = t;
- if(L == R) {
- tree[v].sum = tree[v].tag = tree[v].maxv = tree[v].maxtag = t;
- tree[v].cover = (tree[v].tag > );
- } else tree[v] = calc(tree[v<<],tree[v<<|],t);
- } else {
- int mid = (L + R)>>;
- if(rt <= mid) update(L,mid,lt,rt,t,v<<);
- else if(lt > mid) update(mid+,R,lt,rt,t,v<<|);
- else {
- update(L,mid,lt,rt,t,v<<);
- update(mid+,R,lt,rt,t,v<<|);
- }
- tree[v] = calc(tree[v<<],tree[v<<|],tree[v].tag);
- }
- }
- int main() {
- int kase,op,x,y,t;
- scanf("%d",&kase);
- while(kase--) {
- scanf("%d%d",&n,&m);
- build(,n,);
- while(m--) {
- scanf("%d%d%d",&op,&x,&y);
- if(!op) {
- scanf("%d",&t);
- update(,n,x,y,t,);
- } else if(op == ) printf("%d\n",query(,n,x,y,).maxv);
- else printf("%I64d\n",query(,n,x,y,).sum);
- }
- }
- return ;
- }
哥终于搞清了,感谢 某岛 的代码
本题的做法有点类似于天龙八部里面虚竹那个下棋场景,死而后生
做法就是:每次更新一段区间的时候,把标记放到本区间,然后,我们要兵马未动,粮草先行
先去下面走一遭,统计下面有多少个不大于t,并且这些不大于t的元素的和
这样就能计算出当前区间的和了?不能?那么最大值呢?别逗了,当前区间的最大值肯定是t啦。
tag?要么就是0,要么就是区间的最大值。不是么?
你说这样都不超时真没天理?是的,我也是这么觉得的。。。每次都推到底,这还不超时。。。我也不知道分摊是如何分摊的
下面是搞清真相后写的另一份代码,代码内附有注释,我想这是你目前所能看到的最详细的解说了,毕竟中学生写的代码,可能是有代沟吧
- #include <bits/stdc++.h>
- using namespace std;
- typedef long long LL;
- const int maxn = ;
- struct node{
- LL sum;
- int cv,mx,tag;
- //cv用来记录该区间有多少个数不大于t
- //mx当然是记录区间的最大值
- //tag是lazy标识啦,这个线段树常客
- //sum...
- }tree[maxn<<];
- void pushup(int v){
- tree[v].sum = tree[v<<].sum + tree[v<<|].sum;
- tree[v].mx = max(tree[v<<].mx,tree[v<<|].mx);
- tree[v].cv = tree[v<<].cv + tree[v<<|].cv;
- }
- int tmp;
- void build(int lt,int rt,int v){
- if(lt == rt){
- scanf("%d",&tmp);
- tree[v].sum = tree[v].mx = tree[v].tag = tmp;
- tree[v].cv = ;
- //cv记录的是不大于t的元素个数
- return;
- }
- tree[v].tag = ;
- int mid = (lt + rt)>>;
- build(lt,mid,v<<);
- build(mid+,rt,v<<|);
- pushup(v);
- }
- void modify(int L,int R,int t,int v){
- if(tree[v].tag && tree[v].tag <= t) return;
- tree[v].tag = t;
- //只有可能是tree[v].tag == 0
- //因为前面calc的时候已经先行走了一遍
- if(tree[v].cv != R - L + ){
- //因为当前区间不大于t的元素不算全区间,所以还有比t大的
- //大的要置成t,所以mx成了t
- tree[v].mx = t;
- tree[v].sum += (LL)t*(R - L + - tree[v].cv);
- tree[v].cv = R - L + ;
- //sum在alc以后 其实代表的是那些不大于t的元素之和
- //现在把大于t的都改成t了,那么现在和是多少?
- }
- }
- void pushdown(int L,int R,int v){
- if(tree[v].tag){
- int mid = (L + R)>>;
- modify(L,mid,tree[v].tag,v<<);
- modify(mid+,R,tree[v].tag,v<<|);
- tree[v].tag = ;
- }
- }
- void calc(int L,int R,int t,int v){
- if(tree[v].mx < t) return;
- if(tree[v].tag >= t) tree[v].tag = ;
- if(L == R){
- tree[v].sum = tree[v].mx = tree[v].tag;
- tree[v].cv = tree[v].tag?:;
- //记录当前不大于t的元素的个数以及他们的和
- return;
- }
- pushdown(L,R,v);
- int mid = (L + R)>>;
- calc(L,mid,t,v<<);
- calc(mid+,R,t,v<<|);
- pushup(v);
- }
- void update(int L,int R,int lt,int rt,int t,int v){
- if(tree[v].mx <= t) return;
- if(lt <= L && rt >= R){
- if(L == R){
- tree[v].sum = tree[v].tag = tree[v].mx = t;
- tree[v].cv = ;
- //强行修改为t,毕竟此处是大于t的,如果不大于t前面return了
- }else calc(L,R,t,v);//先行遍历到底,兵马未动,粮草先行
- modify(L,R,t,v);
- }else{
- pushdown(L,R,v);
- int mid = (L + R)>>;
- if(lt <= mid) update(L,mid,lt,rt,t,v<<);
- if(rt > mid) update(mid+,R,lt,rt,t,v<<|);
- pushup(v);
- }
- }
- int queryMax(int L,int R,int lt,int rt,int v){
- if(lt <= L && rt >= R) return tree[v].mx;
- int mid = (L + R)>>,mx = INT_MIN;
- pushdown(L,R,v);
- if(lt <= mid) mx = max(mx,queryMax(L,mid,lt,rt,v<<));
- if(rt > mid) mx = max(mx,queryMax(mid+,R,lt,rt,v<<|));
- pushup(v);
- return mx;
- }
- LL querySum(int L,int R,int lt,int rt,int v){
- if(lt <= L && rt >= R) return tree[v].sum;
- int mid = (L + R)>>;
- LL sum = ;
- pushdown(L,R,v);
- if(lt <= mid) sum += querySum(L,mid,lt,rt,v<<);
- if(rt > mid) sum += querySum(mid+,R,lt,rt,v<<|);
- pushup(v);
- return sum;
- }
- int main(){
- int kase,n,m,op,x,y,t;
- scanf("%d",&kase);
- while(kase--){
- scanf("%d%d",&n,&m);
- build(,n,);
- while(m--){
- scanf("%d%d%d",&op,&x,&y);
- if(x > y) swap(x,y);
- if(!op){
- scanf("%d",&t);
- update(,n,x,y,t,);
- }else if(op == ) printf("%d\n",queryMax(,n,x,y,));
- else printf("%I64d\n",querySum(,n,x,y,));
- }
- }
- return ;
- }
2015 Multi-University Training Contest 2 hdu 5306 Gorgeous Sequence的更多相关文章
- 2015 Multi-University Training Contest 6 hdu 5357 Easy Sequence
Easy Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- HDU 5306 Gorgeous Sequence[线段树区间最值操作]
Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后 ...
- HDU 5306 Gorgeous Sequence
如果维护max,sum,那么可以得到一个暴力方法,如果t>=max,那可以return,否则往下更新,显然超时. 在上面基础上,再维护一下次大值,与最大值的个数.这样一来,次大值<t< ...
- [HDU] 5306 Gorgeous Sequence [区间取min&求和&求max]
题解: 线段树维护区间取min求和求max 维护最小值以及个数,次小值 标记清除时,分情况讨论 当lazy>max1 退出 当max1>lazy>max2(注意不要有等号) 更新 否 ...
- HDU - 5306 Gorgeous Sequence (吉司机线段树)
题目链接 吉司机线段树裸题... #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3 ...
- HDU - 5306 Gorgeous Sequence 线段树 + 均摊分析
Code: #include<algorithm> #include<cstdio> #include<cstring> #define ll long long ...
- 2015 Multi-University Training Contest 8 hdu 5390 tree
tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...
- 2015 Multi-University Training Contest 8 hdu 5383 Yu-Gi-Oh!
Yu-Gi-Oh! Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: ...
随机推荐
- CF833B The Bakery (线段树+DP)
题目大意:给你一个序列(n<=35000),最多分不大于m块(m<=50),求每个块内不同元素的数量之和的最大值 考试的时候第一眼建图,没建出来,第二眼贪心 ,被自己hack掉了,又随手写 ...
- 数据库范式1NF 2NF 3NF BCNF(实例)通俗易懂的讲解
[转] 数据库范式1NF 2NF 3NF BCNF(实例)通俗易懂的讲解 本文对大多数初学数据库原理的同学绝对是个大福利,哈哈,完完整整的看完此篇博文一定能够清晰地理解数据库的四大范式. ...
- SQL SERVER-identity | @@identity | scope_identity
主键自增 IDENTITY(1,1),MS SQL Server 使用 IDENTITY 关键字来执行 auto-increment 任务. 在上面的实例中,IDENTITY 的开始值是 1,每条新记 ...
- HTML5与后台服务器的数据流动问题
编辑中,尚未完稿...2017.7.14 1345 很多前端开发出来的HTML5可能对于后台开发者来说,并不是很清楚,也许像我一样一知半解.而且真的让人很糊涂的地方就是前端的JS如何与后端的数据库进行 ...
- java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start com
错误如题. 原因:web.xml中的servlet映射<url-pattern> 配置错误 改动正确就可以. 我直接删除了,bug就攻克了. 另一个问题是 xxx.jar fail to ...
- leveldb学习:sstable(2)
block写入:block_builder block.h和.cc里定义了block的entry存储格式和restart,提供了entry的查找接口以及迭代器.那么怎样往写block里写entry呢? ...
- bzoj5204: [CodePlus 2018 3 月赛]投票统计(离散化+暴力)
5204: [CodePlus 2018 3 月赛]投票统计 题目:传送门 题解: 谢谢niang老师的一道sui题 离散化之后直接搞啊(打完之后还错了...) 代码: #include<cst ...
- [Swift]数组(Array)最强解析
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- jqGrid添加删除功能(不和数据库交互)
jqGrid添加删除功能(不和数据库交互) 一.背景需求 项目中需要在前端页面动态的添加行,删除行,上下移动行等,同时还不和数据库交互.一直在用jqGrid展示表格的我们,从没有深入的研究过它,当然看 ...
- jsp表单验证格式