• CodeForces


    Decription

    区间最大字段和 (^+) ,最多选择 (k) 个子段,单点修改。

    (n,qle 10^5,kle 20)

    Solution

    考虑暴力怎么做。

    暴力大费流,拆点流量为 (1) 费用为 (a[i]) ,出点像下一个点的入点连边,增广 (k) 次并到 (costle 0) 为止。

    考虑增广过程,其实就是每次取最大的一段,然后将该段去反(反向费用,退流)。

    然后就可以线段树模拟了。

    #include<bits/stdc++.h>
    using namespace std;
    
    template <class T> void read(T &x) {
    	x = 0; bool flag = 0; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) flag |= ch == '-';
    	for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; flag ? x = ~x + 1 : 0;
    }
    
    //#pragma GCC diagnostic error "-std=c++14"
    
    #define N 100010
    #define rep(i, a, b) for (auto i = (a); i <= (b); ++i)
    #define drp(i, a, b) for (auto i = (a); i >= (b); --i)
    #define ll long long
    #define INF 0x3f3f3f3f
    
    struct Data {
    	int sum, lval, rval, sval, sl, sr, lr, rl;
    	Data(int _sum = 0, int _lval = 0, int _rval = 0, int _sval = 0, int _sl = 0, int _sr = 0, int _lr = 0, int _rl = 0) {
    		sum = _sum, lval = _lval, rval = _rval, sval = _sval, sl = _sl, sr = _sr, lr = _lr, rl = _rl;
    	}
    	void reverse() {
    		sum *= -1, lval *= -1, rval *= -1, sval *= -1;
    	}
    	void init(int t) {
    		lval = rval = sval = INF;
    		if (t) reverse();
    	}
    	void merge(const Data& l, const Data& r, bool t) {
    		sum = l.sum + r.sum;
    		if (t) {
    			lval = max(l.lval, l.sum + r.lval), rval = max(r.rval, r.sum + l.rval);
    			sval = max(max(l.sval, r.sval), l.rval + r.lval);
    		}
    		else {
    			lval = min(l.lval, l.sum + r.lval), rval = min(r.rval, r.sum + l.rval);
    			sval = min(min(l.sval, r.sval), l.rval + r.lval);
    		}
    		lr = (lval == l.lval ? l.lr : r.lr);
    		rl = (rval == r.rval ? r.rl : l.rl);
    		if (sval == l.sval) sl = l.sl, sr = l.sr;
    		else if (sval == r.sval) sl = r.sl, sr = r.sr;
    		else sl = l.rl, sr = r.lr;
    	}
    };
    
    struct Node {
    	Data mx, mn;
    	void init() {
    		mx.init(1), mn.init(0);
    	}
    }T[N << 2];
    
    int n, a[N];
    bool tag[N << 2];
    
    #define ls rt << 1
    #define rs ls | 1
    #define mid (l + r >> 1)
    
    void pushup(Node& now, const Node& l, const Node& r) {
    	now.init();
    	now.mx.merge(l.mx, r.mx, 1), now.mn.merge(l.mn, r.mn, 0);
    }
    
    void pushDown(int rt) {
    	if (tag[rt]) {
    		T[ls].mx.reverse(), T[rs].mx.reverse();
    		T[ls].mn.reverse(), T[rs].mn.reverse();
    		swap(T[ls].mx, T[ls].mn), swap(T[rs].mx, T[rs].mn);
    		tag[ls] ^= 1, tag[rs] ^= 1, tag[rt] = 0;
    	}
    }
    
    void update(int rt, int l, int r, int p) {
    	if (l == r) {
    		T[rt].mn = T[rt].mx = Data(a[l], a[l], a[l], a[l], l, r, l, r);
    		return;
    	}
    	pushDown(rt);
    	p <= mid ? update(ls, l, mid, p) : update(rs, mid + 1, r, p);
    	pushup(T[rt], T[ls], T[rs]);
    }
    
    Node query(int rt, int l, int r, int L, int R) {
    	if (L <= l && r <= R) return T[rt];
    	pushDown(rt);
    	Node ret, lret, rret;
    	ret.init(), lret.init(), rret.init();
    	if (L <= mid) lret = query(ls, l, mid, L, R);
    	if (R > mid) rret = query(rs, mid + 1, r, L, R);
    	if (R <= mid) ret = lret;
    	else if (L > mid) ret = rret;
    	else pushup(ret, lret, rret);
    	return ret;
    }
    
    void update(int rt, int l, int r, int L, int R) {
    	if (L <= l && r <= R) {
    		T[rt].mx.reverse(), T[rt].mn.reverse();
    		swap(T[rt].mx, T[rt].mn);
    		tag[rt] ^= 1;
    		return;
    	}
    	pushDown(rt);
    	if (L <= mid) update(ls, l, mid, L, R);
    	if (R > mid) update(rs, mid + 1, r, L, R);
    	pushup(T[rt], T[ls], T[rs]);
    }
    
    int ans = 0;
    void dfs(int k, int l, int r) {
    	Node ret = query(1, 1, n, l, r);
    	if (ret.mx.sval <= 0) return;
    	ans += ret.mx.sval;
    	update(1, 1, n, ret.mx.sl, ret.mx.sr);
    	if (k - 1) dfs(k - 1, l, r);
    	update(1, 1, n, ret.mx.sl, ret.mx.sr);
    }
    
    int main() {
    	read(n);
    	rep(i, 1, n) read(a[i]), update(1, 1, n, i);
    	int q; read(q);
    	while (q--) {
    		int op; read(op);
    		if (!op) {
    			int p; read(p), read(a[p]);
    			update(1, 1, n, p);
    		}
    		else {
    			int l, r, k; read(l), read(r), read(k);
    			ans = 0, dfs(k, l, r);
    			printf("%d
    ", ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java Web开发——JSP基本语法杂记
    Java Web开发——HTML CSS JavaScript 杂记
    Leetcode#13 Roman to Integer
    Leetcode#20 Valid Parentheses
    Leetcode#88 Merge Sorted Array
    Leetcode#171 Excel Sheet Column Number
    Leetcode#168 Excel Sheet Column Title
    Leetcode#160 Intersection of Two Linked Lists
    Leetcode#6 ZigZag Conversion
    Leetcode#8 String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/aziint/p/9709872.html
Copyright © 2020-2023  润新知