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


    传送门
    考虑用 (segment~tree~beats) 那一套理论,维护区间最小值 (mn) 和严格次小值 (se)
    那么可以直接 (mlog^2n) 维护前三个操作
    考虑维护历史最小值,先维护历史最小标记
    写了写发现 (max) 那个修改不好操作
    对于 (max) 操作来说,只会在 (mn< v <se) 的时候打上标记
    这就相当于区间内等于 (mn) 的权值都要变成 (v)
    那么 (max) 操作就可以变成对区间最小值的加法操作
    (v<se),这样就可以非常方便维护历史最小值了
    具体来说,维护下面几个标记

    1. 区间最小值的加法标记
    2. 区间其它值的加法标记
    3. 区间最小值的历史最小的加法标记
    4. 区间其它值的历史最小的加法标记
      下放的时候判断一下是否是区间最小值就好了
    # include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    namespace IO {
    	const int maxn(1 << 21 | 1);
    
    	char obuf[maxn], ibuf[maxn], *iS, *iT, c, *oS = obuf, *oT = obuf + maxn - 1, st[60];
    	int f, tp;
    	
    	inline char Getc() {
    		return iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, maxn, stdin), (iS == iT ? EOF : *iS++)) : *iS++;
    	}
    
    	template <class Int> inline void In(Int &x) {
    		for (c = Getc(), f = 1; c < '0' || c > '9'; c = Getc()) f = c == '-' ? -1 : 1;
    		for (x = 0; c >= '0' && c <= '9'; c = Getc()) x = (x << 1) + (x << 3) + (c ^ 48);
    		x *= f;
    	}
    
    	inline void Flush() {
    		fwrite(obuf, 1, oS - obuf, stdout);
    		oS = obuf;
    	}
    
    	inline void Putc(char c) {
    		*oS++ = c;
    		if (oS == oT) Flush();
    	}
    
    	template <class Int> inline void Out(Int x) {
    		if (x < 0) Putc('-'), x = -x;
    		if (!x) Putc('0');
    		while (x) st[++tp] = x % 10 + '0', x /= 10;
    		while (tp) Putc(st[tp--]);
    	}
    }
    
    using IO :: In;
    using IO :: Out;
    using IO :: Putc;
    using IO :: Flush;
    
    const int maxn(2e6 + 5);
    const int inf(2e9);
    
    struct Min {
    	int mn1, mn2;
    
    	inline Min operator +(Min b) const {
    		Min c;
    		c.mn1 = min(mn1, b.mn1), c.mn2 = min(mn2, b.mn2);
    		if (b.mn1 ^ c.mn1) c.mn2 = min(c.mn2, b.mn1);
    		if (mn1 ^ c.mn1) c.mn2 = min(c.mn2, mn1);
    		return c;
    	}
    };
    
    Min mn[maxn];
    int n, m, hmn[maxn], addmn1[maxn], addmn2[maxn], addhmn1[maxn], addhmn2[maxn];
    
    inline void Update(int x) {
    	mn[x] = mn[x << 1] + mn[x << 1 | 1], hmn[x] = min(hmn[x << 1], hmn[x << 1 | 1]);
    }
    
    void Build(int x, int l, int r) {
    	int mid;
    	if (l == r) {
    		In(mn[x].mn1), mn[x].mn2 = inf, hmn[x] = mn[x].mn1;
    		return;
    	}
    	mid = (l + r) >> 1;
    	Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r);
    	Update(x);
    }
    
    inline void Puttag(int x, int vmn1, int vmn2, int vhmn1, int vhmn2) {
    	hmn[x] = min(hmn[x], mn[x].mn1 + vhmn1);
    	addhmn1[x] = min(addhmn1[x], addmn1[x] + vhmn1);
    	addhmn2[x] = min(addhmn2[x], addmn2[x] + vhmn2);
    	addmn1[x] += vmn1, addmn2[x] += vmn2, mn[x].mn1 += vmn1;
    	if (mn[x].mn2 ^ inf) mn[x].mn2 += vmn2;
    }
    
    inline void Pushdown(int x) {
    	if (!addmn1[x] && !addmn2[x] && !addhmn1[x] && !addhmn2[x]) return;
    	int ls, rs, now;
    	ls = x << 1, rs = x << 1 | 1, now = min(mn[ls].mn1, mn[rs].mn1);
    	if (now == mn[ls].mn1) Puttag(ls, addmn1[x], addmn2[x], addhmn1[x], addhmn2[x]);
    	else Puttag(ls, addmn2[x], addmn2[x], addhmn2[x], addhmn2[x]);
    	if (now == mn[rs].mn1) Puttag(rs, addmn1[x], addmn2[x], addhmn1[x], addhmn2[x]);
    	else Puttag(rs, addmn2[x], addmn2[x], addhmn2[x], addhmn2[x]);
    	addmn1[x] = addmn2[x] = addhmn1[x] = addhmn2[x] = 0;
    }
    
    void Modify_add(int x, int l, int r, int ql, int qr, int v) {
    	int mid;
    	if (ql <= l && qr >= r) {
    		Puttag(x, v, v, v, v);
    		return;
    	}
    	mid = (l + r) >> 1, Pushdown(x);
    	if (ql <= mid) Modify_add(x << 1, l, mid, ql, qr, v);
    	if (qr > mid) Modify_add(x << 1 | 1, mid + 1, r, ql, qr, v);
    	Update(x);
    }
    
    void Modify_max(int x, int l, int r, int ql, int qr, int v) {
    	int mid;
    	if (mn[x].mn1 >= v) return;
    	if (ql <= l && qr >= r && mn[x].mn2 > v) {
    		Puttag(x, v - mn[x].mn1, 0, v - mn[x].mn1, 0);
    		return;
    	}
    	mid = (l + r) >> 1, Pushdown(x);
    	if (ql <= mid) Modify_max(x << 1, l, mid, ql, qr, v);
    	if (qr > mid) Modify_max(x << 1 | 1, mid + 1, r, ql, qr, v);
    	Update(x);
    }
    
    int Query_min(int x, int l, int r, int ql, int qr) {
    	int mid, ret;
    	if (ql <= l && qr >= r) return mn[x].mn1;
    	mid = (l + r) >> 1, Pushdown(x), ret = inf;
    	if (ql <= mid) ret = Query_min(x << 1, l, mid, ql, qr);
    	if (qr > mid) ret = min(ret, Query_min(x << 1 | 1, mid + 1, r, ql, qr));
    	Update(x);
    	return ret;
    }
    
    int Query_hmin(int x, int l, int r, int ql, int qr) {
    	int mid, ret;
    	if (ql <= l && qr >= r) return hmn[x];
    	mid = (l + r) >> 1, Pushdown(x), ret = inf;
    	if (ql <= mid) ret = Query_hmin(x << 1, l, mid, ql, qr);
    	if (qr > mid) ret = min(ret, Query_hmin(x << 1 | 1, mid + 1, r, ql, qr));
    	Update(x);
    	return ret;
    }
    
    int main() {
    	int i, op, l, r, v;
    	In(n), In(m), Build(1, 1, n);
    	while (m) {
    		--m, In(op), In(l), In(r);
    		if (op == 1) In(v), Modify_add(1, 1, n, l, r, v);
    		else if (op == 2) In(v), Modify_max(1, 1, n, l, r, v);
    		else if (op == 3) Out(Query_min(1, 1, n, l, r)), Putc('
    ');
    		else Out(Query_hmin(1, 1, n, l, r)), Putc('
    ');
    	}
        return Flush(), 0;
    }
    
  • 相关阅读:
    面试题目
    MyEclipse 启动 tomcat时错误处理
    js 剪贴板操作
    PHP面试题
    MySQL 数据库 source 导入乱码
    php 不用通过表单也能创建HTTPpost请求
    一个css中zindex的用法
    最新黑链代码expression:隐藏链接代码
    测试网站访问速度的几个小方法
    优秀开源外贸网店程序一览
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/10251754.html
Copyright © 2020-2023  润新知