……一道丧病线段树膜板题……

被常数卡的死去活来……QAQ

学到了些奇技淫巧:把取min标记 和 区间最小值 合并

可以快很多……

#include <bits/stdc++.h>
#define lc(t) ((t) << 1)
#define rc(t) (((t) << 1) | 1)
#define N 2000010
#define INF 1000000000
#define LL long long template <class T> inline T &read(T &x)
{
static int f;
static char c;
for (f = ; !isdigit(c = getchar()); ) {
if (c == '-')
f = -;
}
for (x = ; isdigit(c); c = getchar()) {
x = x * + c - ;
}
return x *= f;
} template <class T> inline void write(T x, const char p = '\n')
{
static int top;
static int s[];
if (x < ) {
x = -x;
putchar('-');
}
do s[++ top] = x % + ;
while (x /= );
while (top)
putchar(s[top --]);
putchar(p);
} using namespace std;
int n, m;
int mn[N], mx[N], cn[N], cx[N], sn[N], sx[N]; LL sum[N];
int t_a[N], t_n[N], t_x[N], i_n[N], i_x[N];
int lb[N], rb[N];
inline void upd(register int t)
{
sum[t] = sum[lc(t)] + sum[rc(t)];
if (mn[lc(t)] == mn[rc(t)])
mn[t] = mn[lc(t)], cn[t] = cn[lc(t)] + cn[rc(t)], sn[t] = min(sn[lc(t)], sn[rc(t)]);
else if (mn[lc(t)] < mn[rc(t)])
mn[t] = mn[lc(t)], cn[t] = cn[lc(t)], sn[t] = min(sn[lc(t)], mn[rc(t)]);
else
mn[t] = mn[rc(t)], cn[t] = cn[rc(t)], sn[t] = min(mn[lc(t)], sn[rc(t)]); if (mx[lc(t)] == mx[rc(t)])
mx[t] = mx[lc(t)], cx[t] = cx[lc(t)] + cx[rc(t)], sx[t] = max(sx[lc(t)], sx[rc(t)]);
else if (mx[lc(t)] > mx[rc(t)])
mx[t] = mx[lc(t)], cx[t] = cx[lc(t)], sx[t] = max(sx[lc(t)], mx[rc(t)]);
else
mx[t] = mx[rc(t)], cx[t] = cx[rc(t)], sx[t] = max(mx[lc(t)], sx[rc(t)]); }
void build(int t, int l, int r)
{
lb[t] = l; rb[t] = r;
if (l == r)
{
int x;
read(x);
mn[t] = mx[t] = sum[t] = x; cn[t] = cx[t] = ; sn[t] = INF; sx[t] = -INF;
}
else
{
build(lc(t), l, (l + r) / );
build(rc(t), (l + r) / + , r);
upd(t);
}
}
inline void add(register int t, int d)
{
sum[t] += (LL)d * (rb[t] - lb[t] + );
mn[t] += d; mx[t] += d; sn[t] += d; sx[t] += d;
t_a[t] += d;
} template <class T> inline void chkmin(T &x, T y) { x > y && (x = y); }
template <class T> inline void chkmax(T &x, T y) { x < y && (x = y); }
inline void m_x(register int t, int d)
{
sum[t] += (LL)cn[t] * (d - mn[t]);
mn[t] = d; chkmax(mx[t], d);
if (mx[t] == mn[t])
{
cx[t] = cn[t] = rb[t] - lb[t] + ;
sum[t] = (LL)mx[t] * (rb[t] - lb[t] + );
sn[t] = INF; sx[t] = -INF;
}
else chkmax(sx[t], d);
}
inline void m_n(register int t, int d)
{
sum[t] += (LL)cx[t] * (d - mx[t]);
mx[t] = d; chkmin(mn[t], d);
if (mx[t] == mn[t])
{
cx[t] = cn[t] = rb[t] - lb[t] + ;
sum[t] = (LL)mx[t] * (rb[t] - lb[t] + );
sn[t] = INF; sx[t] = -INF;
}
else chkmin(sn[t], d);
}
inline void psdw(register int t)
{
if (t_a[t])
{
add(lc(t), t_a[t]);
add(rc(t), t_a[t]);
t_a[t] = ;
}
if (mx[lc(t)] > mx[t] && sx[lc(t)] < mx[t]) m_n(lc(t), mx[t]);
if (mx[rc(t)] > mx[t] && sx[rc(t)] < mx[t]) m_n(rc(t), mx[t]);
if (mn[lc(t)] < mn[t] && sn[lc(t)] > mn[t]) m_x(lc(t), mn[t]);
if (mn[rc(t)] < mn[t] && sn[rc(t)] > mn[t]) m_x(rc(t), mn[t]);
}
namespace segment
{
int l, r, d;
void seg_add(int t)
{
if (l <= lb[t] && rb[t] <= r)
{
add(t, d);
return;
}
psdw(t);
if (l <= rb[lc(t)]) seg_add(lc(t));
if (r >= lb[rc(t)]) seg_add(rc(t));
upd(t);
}
void seg_m_x(int t)
{
if (mn[t] >= d) return;
if (l <= lb[t] && rb[t] <= r && sn[t] > d)
{
m_x(t, d);
return;
}
psdw(t);
if (l <= rb[lc(t)]) seg_m_x(lc(t));
if (r >= lb[rc(t)]) seg_m_x(rc(t));
upd(t);
}
void seg_m_n(int t)
{
if (mx[t] <= d) return;
if (l <= lb[t] && rb[t] <= r && sx[t] < d)
{
m_n(t, d);
return;
}
psdw(t);
if (l <= rb[lc(t)]) seg_m_n(lc(t));
if (r >= lb[rc(t)]) seg_m_n(rc(t));
upd(t);
}
LL get_sum(int t)
{
if (l <= lb[t] && rb[t] <= r)
{
return sum[t];
}
LL d = ;
psdw(t);
if (l <= rb[lc(t)]) d += get_sum(lc(t));
if (r >= lb[rc(t)]) d += get_sum(rc(t));
return d;
}
int get_max(int t)
{
if (l <= lb[t] && rb[t] <= r)
{
return mx[t];
}
int d = -INF;
psdw(t);
if (l <= rb[lc(t)]) d = max(d, get_max(lc(t)));
if (r >= lb[rc(t)]) d = max(d, get_max(rc(t)));
return d;
}
int get_min(int t)
{
if (l <= lb[t] && rb[t] <= r)
{
return mn[t];
}
int d = INF;
psdw(t);
if (l <= rb[lc(t)]) d = min(d, get_min(lc(t)));
if (r >= lb[rc(t)]) d = min(d, get_min(rc(t)));
return d;
}
} int main()
{
read(n);
build(, , n);
read(m);
while (m --)
{
using namespace segment;
int opt;
read(opt); read(l); read(r);
if (opt <= ) read(d);
switch (opt)
{
case : seg_add(); break;
case : seg_m_x(); break;
case : seg_m_n(); break;
case : write(get_sum()); break;
case : write(get_max()); break;
case : write(get_min()); break;
}
}
//write(c, ' '); write(d);
}

bzoj 4695: 最假女选手的更多相关文章

  1. bzoj 4695 最假女选手 吉利线段树

    最假女选手 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 480  Solved: 118[Submit][Status][Discuss] Desc ...

  2. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

  3. bzoj 4695: 最假女选手 && Gorgeous Sequence HDU - 5306 && (bzoj5312 冒险 || 小B的序列) && bzoj4355: Play with sequence

    算导: 核算法 给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量. 当实际代价小于摊还代价时,增加等于差额的 ...

  4. BZOJ 4695 最假女选手 线段树

    题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x  2.把一个区间[L,R] 里小于x 的数变成x  3.把一个区间[L,R] 里大于x ...

  5. BZOJ4695 最假女选手(势能线段树)

    BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...

  6. bzoj4695 最假女选手

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4695 [题解] SegmentTree beats!(见jiry_2论文/营员交流) 考虑只 ...

  7. BZOJ4695:最假女选手

    浅谈区间最值操作和历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html 题目传送门:https://lydsy.com/JudgeOnline/pr ...

  8. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  9. 【bzoj4695】最假女选手 线段树区间最值操作

    题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...

随机推荐

  1. [LeetCode] Construct Binary Tree from Inorder and Postorder Traversal 由中序和后序遍历建立二叉树

    Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume tha ...

  2. [LeetCode] Spiral Matrix 螺旋矩阵

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  3. 51Nod 1268 和为K的组合

    51Nod  1268  和为K的组合 1268 和为K的组合 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 给出N个正整数组成的数组A,求能否从中选出若干个,使 ...

  4. Node中的定时器详解

    在大多数的业务中,我们都会有一些需求,例如几秒钟实现网页的跳转,几分钟对于后台数据进行清理,node与javascript都具有将代码延迟一段时间的能力.在node中可以使用三种方式实现定时功能:超时 ...

  5. DrawerLayout 和 NavigationView 的使用

    参考: 1.NavigationView 的使用 2.NavigationView更改菜单icon和title颜色变化效果 3.Android 自己实现 NavigationView 转了第一篇   ...

  6. 【BZOJ 4579】【Usaco2016 Open】Closing the Farm

    http://www.lydsy.com/JudgeOnline/problem.php?id=4579 把时间倒过来,只是加点,并查集维护连通块. #include<cstdio> #i ...

  7. 文件共享锁定数溢出-IWorkspaceEdit.StopEditing

    在批量保存Feature至本地mdb的时候,当Feature的数量超过一定的值(该值不确定是不是Access文件的MaxLocksPerFile值,因为当MaxLocksPerFile为9500时,F ...

  8. java学习笔记之线程2wait和notifyAll

    2.乐观锁和悲观锁 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到 ...

  9. 重复加载同一个jqgrid

    重复加载同一个jqgrid时需要先清除原先的数据,再进行加载新的数据: 清除时使用方法:jQuery.jgrid.gridUnload('jqGridId'); 同时还有一个GridDestroy的方 ...

  10. 架构师养成记--6.单例和多线程、ThreadLocal

    一.ThreadLocal 使用wait/notify方式实现的线程安全,性能将受到很大影响.解决方案是用空间换时间,不用锁也能实现线程安全. 来看一个小例子,在线程内的set.get就是thread ...