先讲个故事。。。
  据说某一天,claris扔了一道题到某群里面然后引起了不大的讨论~然后好学向上的whx同学发现了这题。。。聪明的whx想了很久。。。然后!whx发现看不懂claris给的暴力的证明。。。于是去找了吉司机。。。吉司机若有所思。。。再后来跟whx说:这是对的。。。然而whx同学并没有写。。。最后就弃坑啦。。。
  第二年,whx来到WC2016的会场上,发现:诶,吉司机的线段树怎么这么。。。眼熟?
  自行脑补
  咳咳,回到正题。
  去了WC2016的都知道这类取max的题的做法。
  容易发现线段树直接做不太好做,尝试深入发掘一下线段树的性质。
  假设我们需要对i∈[l,r]i\in [l,r]进行Ai→max{Ai,x}A_i\rightarrow max\{A_i,x\}的操作,考虑用线段树瞎搞。对每个节点uu维护最小值mn[u]mn[u]和次小值se[u]se[u],那么我们可以对vv进行分类讨论。
当v<=mn[u]v时不鸟它。当mn[u]<v<se[u]mn[u]时我们可以打一个“最小值的cover标记”,把最小值都给设成vv。当v>=se[u]v>=se[u]的时候继续暴力修改下去直到当前区间满足条件。jry和lzz的营员交流证明了这个做法总复杂度是O((m+n)logn)O((m+n)\log n)的。然而总是有一种这玩意是两个log的错觉
  于是到这道题里面就差不多地搞了。首先我们可以把操作2归约成一个最小值增加操作和区间增加操作。然后操作1可以变成max{Ai−inf,0}\max\{A_i-inf,0\},再区间加上CC。注意这个做法不小心的话会爆掉long long。还有一种做法是增加一个区间cover标记,这样常数会小一些。操作3直接搞就好了。
注意代码实现的时候有不少的坑点,比如最小值增量标记必须在mn[u]<v<se[u]mn[u]的时候打,下传标记的时候要注意判一下最小值是否相等。
  复杂度O((n+m)logn)O((n+m)\log n)。
  
  

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = a , _ = b;i <= _;i ++)
#define maxn 300007inline int rd() {char c = getchar();while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;if (c == '-') f = -1 ; else x = c - '0';while (isdigit(c = getchar())) x = x * 10 + c - '0';return x * f;
}const int maxs = 1500007;typedef long long ll;typedef ll  seg[maxs];
typedef int arr[maxn];arr a;
int n , m;#define lc (u << 1)
#define rc (u << 1 | 1)
#define T int u = 1 , int l = 1 , int r = n
#define U u , l , r
#define L lc , l , m
#define R rc , m + 1 , r
#define current ql <= l && r <= qrconst ll inf = 1000000000000ll;static int DBG_CLOCK = 0;#define ASS //printf("current time %d\n" , ++ DBG_CLOCK),assert(sum[u] > 0);struct SegTree {ll tag[maxs][3];seg mn , se , sum;int ql , qr;ll v;//tag0 : cover ; tag1 : add ; tag3 : delta of minimuminline void mt(int u) {mn[u] = min(mn[lc] , mn[rc]);if (mn[lc] == mn[rc])sum[u] = sum[lc] + sum[rc] , se[u] = min(se[lc] , se[rc]);if (mn[lc] != mn[rc]) {if (mn[lc] > mn[rc])se[u] = min(mn[lc] , se[rc]) , sum[u] = sum[rc];elsese[u] = min(mn[rc] , se[lc]) , sum[u] = sum[lc];}ASS}inline void mark_cover(ll v , T) {tag[u][0] = v;mn[u] = v , se[u] = inf;tag[u][1] = tag[u][2] = 0;sum[u] = r - l + 1;
//      printf("%d %d %d\n" , u , l , r);ASS}inline void mark_add(ll v , T) {tag[u][1] += v;mn[u] -= v;if (se[u] != inf) se[u] -= v;}inline void mark_delta(ll v , T) {tag[u][2] += v;mn[u] -= v;}inline bool mark_modi(T) {if (v <= mn[u]) {mark_add(v , U);} else if (mn[u] < v && v < se[u]) { // v !!!!!= se[u]mark_delta(mn[u] - v , U);mark_add(v , U);} else { // v >= se[u] , modify forcelyif (l == r)return (mn[u] = 0 , se[u] = inf , sum[u] = 1) , 1;elsereturn 0;}return 1;}inline void push(T) {int m = (l + r) >> 1;if (tag[u][0] != -1) {mark_cover(tag[u][0] , L) , mark_cover(tag[u][0] , R);tag[u][0] = -1;}if (tag[u][1]) {mark_add(tag[u][1] , L) , mark_add(tag[u][1] , R);tag[u][1] = 0;}if (tag[u][2]) {if (mn[lc] - tag[u][2] == mn[u]) mark_delta(tag[u][2] , L);if (mn[rc] - tag[u][2] == mn[u]) mark_delta(tag[u][2] , R);tag[u][2] = 0;}}void build(T) {tag[u][0] = -1;if (l == r) {mn[u] = a[l] , se[u] = inf;sum[u] = 1;return;}int m = (l + r) >> 1;build(L) , build(R);mt(u);}int que(T) {if (l != r)push(U);if (current)return mn[u] == 0 ? sum[u] : 0;int m = (l + r) >> 1 , t = 0;if (ql <= m) t += que(L);if (qr >  m) t += que(R);return t;}void cover(T) {if (l != r)push(U);if (current){ mark_cover(v , U) ; return ; }int m = (l + r) >> 1;if (ql <= m) cover(L);if (qr >  m) cover(R);mt(u);}void modi(T) {if (l != r)push(U);if (current) if (mark_modi(U))return;int m = (l + r) >> 1;if (ql <= m) modi(L);if (qr >  m) modi(R);mt(u);}inline int Q(int l , int r) {ql = l , qr = r;return que();}inline void S(int l , int r , ll w) {ql = l , qr = r , v = w;cover();}inline void M(int l , int r , ll w) {ql = l , qr = r , v = w;modi();}inline void B() {build();}
}num;void input() {n = rd() , m = rd();rep (i , 1 , n) a[i] = rd();num.B();
}void SetVal(int l , int r) {int v = rd();
//  num.M(l , r , -inf + 1);
//  num.M(l , r , v);num.S(l , r , v);
}void Change(int l , int r) {int v = - rd();num.M(l , r , v);
}void query(int l , int r) {int ans = num.Q(l , r);printf("%d\n" , ans);
}void solve() {rep (i , 1 , m) {int t = rd() , l = rd() , r = rd();if (t == 1)SetVal(l , r);else if (t == 2)Change(l , r);elsequery(l , r);}
}int main() {#ifndef ONLINE_JUDGEfreopen("data.txt" , "r" , stdin);freopen("data.out" , "w" , stdout);#endifinput();solve();return 0;
}

【 bzoj 4355 】 Play with sequence - 线段树乱搞相关推荐

  1. BZOJ 2143 飞飞侠(线段树优化建边 / 并查集优化最短路)【BZOJ修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2143 是 hydro 的 BZOJ ...

  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. BZOJ 1901 Dynamic Rankings(线段树+treap)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1901 题意:给出一个数列,两种操作:(1)询问区间第K小值:(2)修改某个位置的值. 思 ...

  5. BZOJ.2212.[POI2011]Tree Rotations(线段树合并)

    题目链接 \(Description\) 给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n).可以任意的交换两棵子树.问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少 ...

  6. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  7. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  8. BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)

    裸的线段树...因为数组开小了而一直RE..浪费了好多时间.. -------------------------------------------------------------------- ...

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

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

最新文章

  1. 分布式理论(一) - CAP定理
  2. C语言加取址符的作用,C语言中指针和取地址符的关系
  3. rman备份,crontab计划任务没有生成备份文件
  4. linux 4.1.16 ftrace 进程调度,Linux内核进程调度overview(1)
  5. Packet for query is too large(1767212 1048576)mysql在存储图片时提示图片过大
  6. SQL Server2008的数据导入到SQL Server2005
  7. 这个开源的视频编辑项目,有点6~
  8. 机器人避障技术解读 与解决方案
  9. ASP.NET实现PDF大文件的浏览
  10. c语言中函数指针用法,C语言函数指针的用法
  11. 怎么装办公系统服务器,怎么安装oa系统教程
  12. 【2022】保姆级Android studio+JDK下载安装配置教程(带视频)
  13. delphi完美经典--第十八章
  14. KYLO的数据库知识总结
  15. 【GIS风暴】什么是EPSG?常见坐标系对应的EPSG代号、经度范围、中央经线是多少?
  16. 数字化会议管理系统,实现会议全流程管理
  17. SAP 生产成本明细报表
  18. python去除字符串中的单词_从字符串中删除特定单词的最有效方法
  19. 报错 Delete `··` prettier/prettier解决方法
  20. LoadBalancer集成Nacos实现负载均衡

热门文章

  1. Froyo 自动编译方法
  2. 8-Android之adb命令
  3. 项目管理概念——projects、programs、portfolio、operations以及OPM
  4. Task 05:样式色彩秀芳华
  5. 亵渎小说介绍_亵渎行不通
  6. 2019 年终回顾:不忘初心,负重前行
  7. 宏碁 (ACER) TravelMate P449-G2-MG安装Win7系统
  8. 365值得吗 office_对于一个大学生来说,Office365是否值得购买?
  9. Linux虚拟机无法显示IP的解决办法
  10. 电子信息工程跨考计算机武大,我考研的一些经历吧——电气(武汉大学)