题意
- 有\(10^5\)个集合,有两种操作,一是往一个区间中的集合添加一个元素,二是询问一段区间,回答区间中每个集合最小的正数和最大的负数的绝对值之和的和,如果有一种数没出现过那么这个集合的答案就是\(0,q <= 5×10^4\)
之前没有写过吉司机线段树,这个题网上也没有\(Solution\),所以在\(CF\)上找了一个人的代码学板子,对着各种资料东拼西凑一晚上才过掉。
首先对于正数负数分开考虑,那么操作就变成了区间取\(min\)和区间求和,这个东西用吉司机线段树可以很好完成,维护区间最大值\(mx\),次大值\(smx\),最大值个数\(nmx\),区间取\(min\)标记\(tag\),设当前修改的权值是\(val\),\(mx <= val\)直接退出就好了,\(smx < val < mx\) 修改最大值就好了,\(val < smx\) 向下递归,这个东西复杂度是两个\(log\)的,可以用势能分析证明...我也不会就不证了。
对于这个题多维护一个区间是否全部有值\(allin\),\(pushup\)用\(vector\)可以实现的很巧妙,就把四个值都放进去 然后排序去重,最大的就是最大值 第二个就是次大值,\(pushdown\)就把标记下放,如果更新了子区间标记的话,就把子区间的答案更新,更新的过程也很简单,看代码应该都能理解。
\(update:\)
我这种\(pushup\)的写法巨慢...不如一个个\(if\)..
void pushup(int bh) {
int lc = ls, rc = rs;
allin[bh] = allin[lc] & allin[rc], sum[bh] = sum[lc] + sum[rc];
if(mx[lc] == mx[rc]) {
mx[bh] = mx[lc], nmx[bh] = nmx[lc] + nmx[rc];
smx[bh] = max(smx[lc], smx[rc]);
} else {
if(mx[lc] < mx[rc]) swap(lc, rc);
mx[bh] = mx[lc], nmx[bh] = nmx[lc];
smx[bh] = max(smx[lc], mx[rc]);
}
}
Codes
#include<bits/stdc++.h>
#include<bits/extc++.h>
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define FOR(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define debug(x) cout << #x << " = " << x << endl
#define mem(a, b) memset(a, b, sizeof(a))
#define cpy(a, b) memcpy(a, b, sizeof(a))
#define min(a, b) (a < b ? a : b)
#define max(a, b) (b < a ? a : b)
#define inf (0x3f3f3f3f)
#define INF (1e18)
#define pb push_back
#define mp make_pair
#define x first
#define y second
typedef unsigned long long ull;
typedef unsigned int uint;
typedef long long ll;
typedef std::pair<ll, int> PLI;
typedef std::pair<int, int> PII;
typedef long double ldb;
typedef double db;
namespace IO {
#define getc() ((S_ == T_) && (T_ = (S_ = Ch_) + fread(Ch_, 1, Buffsize, stdin), S_ == T_) ? 0 : *S_ ++)
#define putc(x) *nowps ++ = (x)
const uint Buffsize = 1 << 15, Output = 1 << 23;
static char Ch_[Buffsize], *S_ = Ch_, *T_ = Ch_;
static char Out[Output], *nowps = Out;
inline void flush(){fwrite(Out, 1, nowps - Out, stdout); nowps = Out;}
template<class T>inline void read(T &_) {
_ = 0; static char __; T ___ = 1;
for(__ = getc(); !isdigit(__); __ = getc()) if(__ == '-') ___ = -1;
for(; isdigit(__); __ = getc()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
_ *= ___;
}
template<class T>inline void write(T _, char __ = '\n') {
if(!_) putc('0');
if(_ < 0) putc('-'), _ = -_;
static uint sta[111], tp;
for(tp = 0; _; _ /= 10) sta[++ tp] = _ % 10;
for(; tp; putc(sta[tp --] ^ 48)); putc(__);
}
template<class T>inline bool chkmax(T &_, T __) {return _ < __ ? _ = __, 1 : 0;}
template<class T>inline bool chkmin(T &_, T __) {return _ > __ ? _ = __, 1 : 0;}
}
using namespace std;
using namespace IO;
const int N = 1e5 + 10;
const int n = 1e5;
struct Segment_Tree {
#define ls (bh << 1)
#define rs (ls | 1)
#define mid ((l + r) >> 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
ll sum[N << 2]; bool allin[N << 2];
int nmx[N << 2], mx[N << 2], smx[N << 2], tag[N << 2];
void modify(int bh, int val) {
sum[bh] -= (ll)allin[bh] * mx[bh] * nmx[bh];
chkmin(tag[bh], val), chkmin(mx[bh], val);
sum[bh] += (ll)mx[bh] * nmx[bh] * (allin[bh] = 1);
}
void pushup(int bh) {
allin[bh] = allin[ls] & allin[rs], sum[bh] = sum[ls] + sum[rs];
vector<int> vp = {-inf, mx[ls], smx[ls], mx[rs], smx[rs]};
sort(vp.begin(), vp.end());
vp.erase(unique(vp.begin(), vp.end()), vp.end());
mx[bh] = vp.back(), smx[bh] = vp[vp.size() - 2];
nmx[bh] = (mx[bh] == mx[ls]) * nmx[ls] + (mx[bh] == mx[rs]) * nmx[rs];
}
void pushdown(int bh) {
if(tag[bh] ^ inf) modify(ls, tag[bh]), modify(rs, tag[bh]), tag[bh] = inf;
}
void build(int bh, int l, int r) {
tag[bh] = mx[bh] = inf, smx[bh] = -inf;
nmx[bh] = r - l + 1, sum[bh] = allin[bh] = 0;
if(l ^ r) build(lson), build(rson);
}
void update(int bh, int l, int r, int x, int y, int z) {
if(y < l || x > r || mx[bh] <= z) return;
if(x <= l && r <= y && smx[bh] <= z) modify(bh, z);
else {
pushdown(bh);
update(lson, x, y, z);
update(rson, x, y, z);
pushup(bh);
}
}
}T[2];
ll query(int bh, int l, int r, int x, int y) {
if(y < l || x > r || !T[0].sum[bh] || !T[1].sum[bh]) return 0;
if(x <= l && r <= y && T[0].allin[bh] && T[1].allin[bh])
return T[0].sum[bh] + T[1].sum[bh];
T[0].pushdown(bh), T[1].pushdown(bh);
return query(lson, x, y) + query(rson, x, y);
}
int main() {
#ifdef ylsakioi
file("cf885f");
#endif
int q, opt, x, y, z;
T[0].build(1, 1, n), T[1].build(1, 1, n);
for(read(q); q -- ; ) {
read(opt), read(x), read(y); -- y;
if(opt == 1) read(z), T[z > 0].update(1, 1, n, x, y, abs(z));
else write(query(1, 1, n, x, y));
}
return flush(), 0;
}