题目大意:给你一个序列a,你有三个操作,0: x y t将a[x,y]和t取min;1:x y求a[x,y]的最大值;2:x y求a[x,y]的sum

题解:首先很明显就是线段树裸题,那么考虑如何维护

区间最大值和区间sum很好维护,0操作不好做,那么考虑怎么快速解决0操作

很容易想到维护区间最大值和区间是否全部相同,这是一个做法,但是时间复杂度上却不正确,但也给了我们一个思路,可以通过维护最大值之类的数来加快操作

一个不行就两个,于是考虑维护次大值,那么每次0操作就有三种情况,一:比区间最大值还大,那么直接返回;二:大于区间次大值小于区间最大值,那么可以直接修改区间;三:小于区间次大值,那么继续递归下去;

这么做是可行的,在更新区间时因为要维护sum值,于是多维护一个区间max有多少个即可

证明略,时间复杂度o(nlog^2n)——来源:吉老师

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
int T,n,m;
ll a[1000001];
class Segtree
{
public:ll sum[1000001*5],mx[1000001*5],smx[1000001*5],cnt[1000001*5],fl[1000001*5];void pushup(int pos){sum[pos]=sum[pos<<1]+sum[pos<<1|1];if(mx[pos<<1]>mx[pos<<1|1]){mx[pos]=mx[pos<<1];cnt[pos]=cnt[pos<<1];if(mx[pos<<1|1]>smx[pos<<1])smx[pos]=mx[pos<<1|1];else smx[pos]=smx[pos<<1];}if(mx[pos<<1]<mx[pos<<1|1]){mx[pos]=mx[pos<<1|1];cnt[pos]=cnt[pos<<1|1];if(mx[pos<<1]>smx[pos<<1|1])smx[pos]=mx[pos<<1];else smx[pos]=smx[pos<<1|1];}if(mx[pos<<1]==mx[pos<<1|1]){mx[pos]=mx[pos<<1];cnt[pos]=cnt[pos<<1]+cnt[pos<<1|1];if(smx[pos<<1]>smx[pos<<1|1])smx[pos]=smx[pos<<1];else smx[pos]=smx[pos<<1|1];}}void pushdown(int pos){if(fl[pos]>=0){if(mx[pos<<1]>fl[pos]){sum[pos<<1]-=(mx[pos<<1]-fl[pos])*cnt[pos<<1];fl[pos<<1]=mx[pos<<1]=fl[pos];}if(mx[pos<<1|1]>fl[pos]){sum[pos<<1|1]-=(mx[pos<<1|1]-fl[pos])*cnt[pos<<1|1];fl[pos<<1|1]=mx[pos<<1|1]=fl[pos];}fl[pos]=-1;}}void build(int l,int r,int pos){if(l==r){sum[pos]=mx[pos]=a[l];cnt[pos]=1;fl[pos]=smx[pos]=-1;return;}int mid=l+r>>1;build(l,mid,pos<<1);build(mid+1,r,pos<<1|1);pushup(pos);fl[pos]=-1;}void change(int l,int r,int al,int ar,ll v,int pos){int mid=l+r>>1;if(l==al && r==ar){if(v>=mx[pos])return;if(smx[pos]<v && v<mx[pos]){sum[pos]-=(mx[pos]-v)*cnt[pos];fl[pos]=mx[pos]=v;return;}change(l,mid,al,mid,v,pos<<1);change(mid+1,r,mid+1,ar,v,pos<<1|1);pushup(pos);return;}pushdown(pos);if(ar<=mid)change(l,mid,al,ar,v,pos<<1);if(al>mid)change(mid+1,r,al,ar,v,pos<<1|1);if(al<=mid && ar>mid){change(l,mid,al,mid,v,pos<<1);change(mid+1,r,mid+1,ar,v,pos<<1|1);}pushup(pos);}ll askmax(int l,int r,int al,int ar,int pos){if(l==al && r==ar)return mx[pos];int mid=l+r>>1;pushdown(pos);if(ar<=mid)return askmax(l,mid,al,ar,pos<<1);if(al>mid)return askmax(mid+1,r,al,ar,pos<<1|1);if(al<=mid && ar>mid){ll t1=askmax(l,mid,al,mid,pos<<1),t2=askmax(mid+1,r,mid+1,ar,pos<<1|1);return t1>t2?t1:t2;}}ll asksum(int l,int r,int al,int ar,int pos){if(l==al && r==ar)return sum[pos];int mid=l+r>>1;pushdown(pos);if(ar<=mid)return asksum(l,mid,al,ar,pos<<1);if(al>mid)return asksum(mid+1,r,al,ar,pos<<1|1);if(al<=mid && ar>mid)return asksum(l,mid,al,mid,pos<<1)+asksum(mid+1,r,mid+1,ar,pos<<1|1);}
}segtree;
int main()
{scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);segtree.build(1,n,1);int mod,x,y;ll t;while(m--){scanf("%d",&mod);if(mod==0){scanf("%d%d%lld",&x,&y,&t);segtree.change(1,n,x,y,t,1);}if(mod==1){scanf("%d%d",&x,&y);printf("%lld\n",segtree.askmax(1,n,x,y,1));}if(mod==2){scanf("%d%d",&x,&y);printf("%lld\n",segtree.asksum(1,n,x,y,1));}}}return 0;
}

心得:有时候多维护一个次大值能解决很多问题,更多时候在不知道如何证明时间复杂度的情况下往往维护次大值是正确的

转载于:https://www.cnblogs.com/worcher/p/11561073.html

【HDU5306】【DTOJ2481】Gorgeous Sequence【线段树】相关推荐

  1. Gorgeous Sequence线段树区间跟新

    http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1018&ojid=0&cid=12578&hide= ...

  2. codeforces CF438D The Child and Sequence 线段树

    $ \Rightarrow $ 戳我进CF原题 D. The Child and Sequence time limit per test: 4 seconds memory limit per te ...

  3. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  4. 2019ICPC(南京) - Greedy Sequence(线段树)

    题目链接:点击查看 题目大意:题意不明(英语渣),网上的简洁版转化: 对于每个i,所在下标p[i],在[p[i]−k,p[i]+k]中找到小于i的最大数x,然后ans[i]=ans[x]+1即可. 题 ...

  5. 【bzoj4355】Play with sequence 线段树区间最值操作

    题目描述 维护一个长度为N的序列a,现在有三种操作: 1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a[V]都赋值为C. 2)给出参数U,V,C,对于区间[U,V]里的每个数 ...

  6. 【 bzoj 4355 】 Play with sequence - 线段树乱搞

    先讲个故事... 据说某一天,claris扔了一道题到某群里面然后引起了不大的讨论~然后好学向上的whx同学发现了这题...聪明的whx想了很久...然后!whx发现看不懂claris给的暴力的证明. ...

  7. UESTC-1546___Bracket Sequence —— 线段树 + 括号序列

    题目链接:点我啊╭(╯^╰)╮ 题目大意: 给出一个括号序列      setsetset -- 将给定区间全部转化为指定括号      reversereversereverse -- 将给定区间的 ...

  8. 【BZOJ4355】Play with sequence 线段树

    [BZOJ4355]Play with sequence Description 维护一个长度为N的序列a,现在有三种操作: 1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a ...

  9. HDU 5828 Rikka with Sequence (线段树+剪枝优化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...

  10. HDU4893 Wow! Such Sequence! 线段树

    题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得 ...

最新文章

  1. 阿里云网盘内测_阿里云网盘内测,下载10M/s;百度网盘...?
  2. nginx服务器的负载均衡和动静分离(未完)
  3. TableLayout(表格布局)
  4. 「3」Java开发环境搭建
  5. Python对文件的三种打开方式以及with管理上下文
  6. vsFTPD编译安装使用实用手册
  7. Java技术大咖为什么都有写博客的习惯呢?
  8. UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xae in position解决办法
  9. arduino IED2.0实现Serial.println打印结果
  10. 程序员对私密聊天的乱想
  11. JavaScrip笔记心得(持续更新)
  12. 使用Python求解方程
  13. Window程序设计(一)
  14. 关于springboot整合mybatisplus中找不到数据库中的表的问题
  15. 安全-流量劫持形成的原因
  16. 中国金融出版社出版的2013版《风险管理》
  17. SQL-高级命令(一)语句:like通配符,as别名
  18. nvm切换不成功:exit status 5: �ܾ����ʡ� exit status 1: ���ļ��Ѵ���ʱ���޷��������ļ���
  19. k1075停运吗_4月16日起,株洲火车站69趟列车调运行时间6对停运
  20. 【激光SLAM】 01 cartographer环境建立以及建图测试(详细级)

热门文章

  1. Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展
  2. X86嵌入式主板在IOT网关产品的应用
  3. 用Python玩转词云
  4. 3、Oracle表空间管理
  5. Unity3D专访——真正的面试
  6. 11.cadence.通孔类封装创建[原创]
  7. 面向对象是软件开发范式的根本性颠覆: 主体建模, 非目标导向, 松耦合, 非逻辑分解, 软件进化...
  8. 看了《为什么你应该写博客》有感
  9. 模拟浏览器自动化测试工具Selenium之七采集网页信息写入excel
  10. 模拟浏览器自动化测试工具Selenium之四cssSelector元素定位开发篇