\(\text{Solution}\)

观察到关于 \(x\) 的函数在 \(n\) 个操作之后一定是这样的:

一段水平直线加上一段斜率为 \(1\) 的直线再加上一段水平直线

于是线段树维护这个分段函数即可

因为我是用斜率为 \(1\) 的直线的起点和终点坐标反应这个函数

所以合并分段函数的时候要处理退化成一条水平直线的情况

然而考场忘了判。。。

不过这个第一次写数据结构维护分段函数呢

当然码量更少且不需要合并函数的做法是分块啦

维护每个块的函数,一次修改直接 \(O(\sqrt n)\) 重构

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define IN inline
using namespace std; template <typename T>
IN void read(T &x) {
x = 0; char ch = getchar(); int f = 0;
for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar());
for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
if (f) x = ~x + 1;
} const int N = 1e5 + 5, len = 2e8;
int n, q; #define ls (p << 1)
#define rs (ls | 1)
#define mid (l + r >> 1) struct SegmentTree {
int x0, x1, y0, y1;
IN int F(int x) {return ((x <= x0) ? y0 : ((x >= x1) ? y1 : x - x0 + y0));}
IN int nF_max(int y) {
return ((y < y0 || y > y1) ? -1 : ((y == y0) ? x0 : ((y == y1) ? len : y - y0 + x0)));
}
IN int nF_min(int y) {
return ((y < y0 || y > y1) ? -1 : ((y == y0) ? 1 : ((y == y1) ? x1 : y - y0 + x0)));
}
}seg[N * 4]; IN void single(int p, int op, int val) {
seg[p].x0 = seg[p].y0 = 1, seg[p].x1 = seg[p].y1 = len;
if (op == 1) seg[p].y0 += val, seg[p].y1 += val;
else if (op == 2) seg[p].x1 = seg[p].y1 = val;
else seg[p].x0 = seg[p].y0 = val;
}
IN void pushup(int p) {
seg[p].y0 = seg[rs].y0, seg[p].y1 = seg[rs].y1;
seg[p].x0 = seg[ls].nF_max(seg[rs].x0);
if (seg[p].x0 == -1) seg[p].x0 = seg[ls].x0, seg[p].y0 = seg[rs].F(seg[ls].y0);
seg[p].x1 = seg[ls].nF_min(seg[rs].x1);
if (seg[p].x1 == -1) seg[p].x1 = seg[ls].x1, seg[p].y1 = seg[rs].F(seg[ls].y1);
if (seg[p].y0 == seg[p].y1) seg[p].x0 = seg[p].x1 = 1;
}
void build(int p, int l, int r) {
if (l == r) {int op, val; read(op), read(val), single(p, op, val); return;}
build(ls, l, mid), build(rs, mid + 1, r), pushup(p);
}
void modify(int p, int l, int r, int x, int op, int val) {
if (l == r) return single(p, op, val), void();
((x <= mid) ? modify(ls, l, mid, x, op, val) : modify(rs, mid + 1, r, x, op, val));
pushup(p);
} int main() {
freopen("function.in", "r", stdin);
freopen("function.out", "w", stdout);
read(n), build(1, 1, n), read(q);
for(int op, pos, val; q; --q) {
read(op), read(pos);
if (op == 4) printf("%d\n", seg[1].F(pos));
else read(val), modify(1, 1, n, pos, op, val);
}
}

最新文章

  1. 动态加载JS 和 CSS
  2. poj3278 Catch That Cow
  3. python类相关
  4. 不同版本strtotime(&quot;2016-09-04&quot;)输出不同问题
  5. MySQL – 导出数据成csv
  6. STL erase函数
  7. 第二百一十八天 how can I 坚持
  8. delphi 中使用WaitForMultipleObjects等待线程执行,再执行后续代码
  9. Cocos2d—X游戏开发之CCScrollView(滑动视图)(十二)
  10. ArrayBuffer和TypedArray,以及Blob的使用
  11. Ubuntu配置OpenStack 二:配置时间同步NTP和安装数据库Maridb以及问题总结
  12. JavaScript系列----面向对象的JavaScript(2)
  13. Java基础---Java---网络编程---TCP、UDP、UDP-键盘录入方式数据、Socket、TCP复制文件、UDP-聊天
  14. 【转载】假设有以下代码 String s = “hello”; 阿里巴巴笔试题
  15. Bloom Filter(布隆过滤器)如何解决缓存穿透
  16. android 显示大图模糊问题
  17. vue element-ui 设置时间组件
  18. JavaScript&amp;Date对象
  19. listview添加数据
  20. selnium远程机上传图片遇到的坑

热门文章

  1. ZWS物联网云平台为电器设备智能化,提升产品竞争力
  2. 谁说.NET没有GC调优?只改一行代码就让程序不再占用内存
  3. SpringCloud Alibaba(七) - JWT(JSON Web Token)
  4. bug处理记录:Error running &#39;WorkflowApplication&#39;: Command line is too long. Shorten command line for WorkflowApplication or also for Spring Boot default configuration?
  5. android nativate 动态注册 静态注册
  6. 深入理解 MySQL 的事务隔离级别和 MVCC 机制
  7. 实施 GitOps 的三个关键步骤
  8. js逆向到加密解密入口的多种方法
  9. JavaScript:如何知道一个变量的数据类型?:typeof
  10. Potree 001 Potree介绍