论文题。

考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记。

我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值。

对于被覆盖一半的区间,讨论一下即可。

对于每个最小值和次小值记录前缀最小值,当前/历史最小值,当到达合法区间的时候:

如果区间最小值>x,直接退出。

如果minv[o]<x<semn[o],那么更新当前的次小值

反之继续向下。

#include<bits/stdc++.h>
const int inf=2e9+;
const int N=;
using namespace std;
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int n,m;
struct Segment_Tree_Beats{
#define lson (o<<1)
#define rson (o<<1|1)
int his[N<<],pra[N<<],prb[N<<],a[N<<],b[N<<],minv[N<<],semn[N<<];
inline void pushup(int o){
if(minv[lson]==minv[rson])minv[o]=minv[lson],semn[o]=min(semn[lson],semn[rson]);
else if(minv[lson]<minv[rson]){minv[o]=minv[lson];semn[o]=min(semn[lson],minv[rson]);}
else{minv[o]=minv[rson];semn[o]=min(semn[rson],minv[lson]);}
his[o]=min(his[lson],his[rson]);
}
inline void puttag(int o,int v){
his[o]=min(his[o],minv[o]+v);
a[o]+=v;b[o]+=v;minv[o]+=v;semn[o]+=v;semn[o]=min(semn[o],inf);
pra[o]=min(pra[o],a[o]);
prb[o]=min(prb[o],b[o]);
}
inline void plus(int o,int ax,int pa,int bx,int pb){
his[o]=min(his[o],minv[o]+pa);
pra[o]=min(pra[o],pa+a[o]);
prb[o]=min(prb[o],pb+b[o]);
a[o]+=ax;b[o]+=bx;minv[o]+=ax;semn[o]+=bx;semn[o]=min(semn[o],inf);
}
inline void pushdown(int o){
int mmmm=min(minv[lson],minv[rson]);
if(minv[lson]==mmmm)plus(lson,a[o],pra[o],b[o],prb[o]);else plus(lson,b[o],prb[o],b[o],prb[o]);
if(minv[rson]==mmmm)plus(rson,a[o],pra[o],b[o],prb[o]);else plus(rson,b[o],prb[o],b[o],prb[o]);
a[o]=b[o]=pra[o]=prb[o]=;
}
inline void build(int o,int l,int r){
if(l==r){
minv[o]=read();his[o]=minv[o];semn[o]=inf;
return;
}
int mid=(l+r)>>;
build(lson,l,mid);build(rson,mid+,r);
pushup(o);
}
inline void optadd(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){puttag(o,v);return;}
int mid=(l+r)>>;pushdown(o);
if(ql<=mid)optadd(lson,l,mid,ql,qr,v);
if(qr>mid)optadd(rson,mid+,r,ql,qr,v);
pushup(o);
}
inline void dfs(int o,int l,int r,int v){
if(minv[o]>=v)return;
if(semn[o]>v){
v-=minv[o];his[o]=min(his[o],minv[o]+v);
pra[o]=min(pra[o],a[o]+v);
a[o]+=v;minv[o]+=v;return;
}
int mid=(l+r)>>;pushdown(o);
dfs(lson,l,mid,v);dfs(rson,mid+,r,v);
pushup(o);
}
inline void change(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){dfs(o,l,r,v);return;}
int mid=(l+r)>>;pushdown(o);
if(ql<=mid)change(lson,l,mid,ql,qr,v);
if(qr>mid)change(rson,mid+,r,ql,qr,v);
pushup(o);
}
inline int querynow(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return minv[o];
int mid=(l+r)>>,ans=inf;pushdown(o);
if(ql<=mid)ans=min(ans,querynow(lson,l,mid,ql,qr));
if(qr>mid)ans=min(ans,querynow(rson,mid+,r,ql,qr));
return ans;
}
inline int queryhis(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return his[o];
int mid=(l+r)>>,ans=inf;pushdown(o);
if(ql<=mid)ans=min(ans,queryhis(lson,l,mid,ql,qr));
if(qr>mid)ans=min(ans,queryhis(rson,mid+,r,ql,qr));
return ans;
}
}T;
int main(){
n=read();m=read();
T.build(,,n);
while(m--){
int opt=read(),l=read(),r=read();
if(opt==){int x=read();T.optadd(,,n,l,r,x);}
if(opt==){int x=read();T.change(,,n,l,r,x);}
if(opt==)printf("%d\n",T.querynow(,,n,l,r));
if(opt==)printf("%d\n",T.queryhis(,,n,l,r));
}
}

【UOJ#169】元旦老人与数列的更多相关文章

  1. 2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)

    传送门 线段树好题. 维护区间加,区间取最大值,维护区间最小值,历史区间最小值. 同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史 ...

  2. uoj169:元旦老人与数列

    题意:http://uoj.ac/problem/169 sol  :线段树..........蜜汁TLE了一个点,不管了..... 代码抄snowMyDream的,orz........... 线段 ...

  3. 网路流 uoj 168 元旦老人与丛林

    http://uoj.ac/problem/168 没想到是网络流 官方题解地址 http://jiry-2.blog.uoj.ac/blog/1115 subtask2告诉我们度数为012的点对答案 ...

  4. UOJ169. 【UR #11】元旦老人与数列

    传送门 考虑用 \(segment~tree~beats\) 那一套理论,维护区间最小值 \(mn\) 和严格次小值 \(se\) 那么可以直接 \(mlog^2n\) 维护前三个操作 考虑维护历史最 ...

  5. [UOJ #167]【UR #11】元旦老人与汉诺塔

    题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...

  6. UOJ 52 元旦激光炮

    http://uoj.ac/problem/52 题意:每次可以得到3个序列中 思路:每次分别取出三个序列的K/3长度的位置,取最小的那个,然后每次减掉它,总复杂度是Nlog3N #include & ...

  7. UR11 A.元旦老人与汉诺塔

    题目:http://uoj.ac/contest/23/problem/167 如果我们拿个map来存状态的话.设当前状态是v,下一个状态是s.有f[i+1][s]+=f[i][v]. 初始f[0][ ...

  8. uoj167 元旦老人与汉诺塔(记忆化搜索)

    QwQ太懒了,题目直接复制uoj的了 QwQ这个题可以说是十分玄学的一道题了 首先可以暴搜,就是\(dfs\)然后模拟每个过程是哪个柱子向哪个柱子移动 不多解释了,不过实现起来还是有一点点难度的 直接 ...

  9. 2018.07.29~30 uoj#170. Picks loves segment tree VIII(线段树)

    传送门 线段树好题. 维护区间取两种最值,区间加,求区间两种历史最值,区间最小值. 自己的写法调了一个晚上+一个上午+一个下午+一个晚上并没有调出来,90" role="prese ...

随机推荐

  1. Python 嵌套函数和闭包

    Python 嵌套函数和闭包 1.函数嵌套 如果在一个函数内部定义了另一个函数,我们称外部的函数为外函数,内部的函数为内函数,如下代码: def out_func(): def inner_func1 ...

  2. (七)Redis对键key的操作

    key的全部命令如下: keys pattern # 查找所有符合给定模式pattern的key ,查找所有key 使用[keys *] del key1 key2 ... # 删除给定的一个或多个k ...

  3. 从APNIC提取IP信息

    从APNIC提取IP信息 https://blog.csdn.net/nullzeng/article/details/17538009 Apnic介绍简而言之,Apnic是全球5个地区级的Inter ...

  4. POJ3581:Sequence——题解

    http://poj.org/problem?id=3581 给一串数,将其分成三个区间并且颠倒这三个区间,使得新数列字典序最小. 参考:http://blog.csdn.net/libin56842 ...

  5. 剑桥offer(51~60)

    51.题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. /* struct TreeLinkNode { ...

  6. 警惕!Unity3D中UnityEngine.Object的一个小陷阱

    先看看如下C#的脚本代码: 猜猜控制台打出来的是什么? In the bool parameter function, value info is:  True 肯定出乎很多人的意料吧? transf ...

  7. HDU 2646 栈的应用 STL

    Expression Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. UVA11426

    链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=26&page ...

  9. html 让一行文字居中

    文本在行高范围内垂直居中 可以利用行高特性让一行文本居中 line-height:100px://父容器的高度

  10. Windows、Linux及Mac查看端口和杀死进程

    本文介绍如何在Windows.Linux及Mac下查看端口和杀死进程. Windows下查看端口和杀死进程 查看占用端口号的进程号:netstat –ano | findstr "指定端口号 ...