首页 > 其他分享 >题解 CF903G【Yet Another Maxflow Problem】

题解 CF903G【Yet Another Maxflow Problem】

时间:2023-10-25 10:22:05浏览次数:43  
标签:CF903G min 题解 ll modify sgt mid Another ql

加边 \(A_n\stackrel{0}{\to}A_{n+1}\),\(B_0\stackrel{0}{\to}B_1\)。称形如 \(A_i\to A_{i+1}\) 的边为左部边,形如 \(B_j\to B_{j+1}\) 的边为右部边,形如 \(A_i\to B_j\) 的边为中间边。

根据最大流最小割定理,将最大流问题转化为最小割问题求解。显然,至少存在一组最小割,包含恰好一条左部边、恰好一条右部边和若干条中间边。

设割了左部边 \(A_i\to A_{i+1}\)、右部边 \(B_j\to B_{j+1}\),则割掉的中间边一定是 \(A_u\to B_v\),其中 \(u\le i\land v > j\)。设此时割掉的所有中间边的容量和为 \(c_{i,j}\),则答案为 \(\min\limits_i\left\{a_i+\min\limits_j\left\{b_j+c_{i,j}\right\}\right\}\)。设 \(p_i=\min\limits_j\left\{b_j+c_{i,j}\right\}\),答案即为 \(\min\limits_i\left\{a_i+p_i\right\}\)。

初始时 \(p_i\) 可通过扫描线求出,由于修改操作是对 \(a_i\) 的单点改,再使用线段树维护单点改、区间 \(\min\) 即可。

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x, y, z) for(ll x = (y); x <= (z); ++x)
#define per(x, y, z) for(ll x = (y); x >= (z); --x)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do {freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);} while(false)
#define endl '\n'
using namespace std;
typedef long long ll;

mt19937 rnd(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
ll randint(ll L, ll R) {
    uniform_int_distribution<ll> dist(L, R);
    return dist(rnd);
}

template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

const ll N = 2e5 + 5;

ll n, m, q, a[N], b[N], p[N];
vector<tuple<ll, ll>> e[N];

struct SegmentTree {
    ll val[N << 2], tag[N << 2];
    #define lc(u) (u << 1)
    #define rc(u) (u << 1 | 1)
    void pushup(ll u) {
        val[u] = min(val[lc(u)], val[rc(u)]);
    }
    void pushdown(ll u) {
        if(!tag[u]) return;
        tag[lc(u)] += tag[u];
        val[lc(u)] += tag[u];
        tag[rc(u)] += tag[u];
        val[rc(u)] += tag[u];
        tag[u] = 0;
    }
    void build(ll* a, ll u, ll l, ll r) {
        tag[u] = 0;
        if(l == r) {
            val[u] = a[l];
            return;
        }
        ll mid = (l + r) >> 1;
        build(a, lc(u), l, mid);
        build(a, rc(u), mid + 1, r);
        pushup(u);
    }
    void modify(ll u, ll l, ll r, ll ql, ll qr, ll k) {
        if(ql <= l && r <= qr) {
            tag[u] += k;
            val[u] += k;
            return;
        }
        pushdown(u);
        ll mid = (l + r) >> 1;
        if(ql <= mid) modify(lc(u), l, mid, ql, qr, k);
        if(qr > mid) modify(rc(u), mid + 1, r, ql, qr, k);
        pushup(u);
    }
    void clear(ll u, ll l, ll r) {
        tag[u] = val[u] = 0;
        if(l == r) return;
        ll mid = (l + r) >> 1;
        clear(lc(u), l, mid);
        clear(rc(u), mid + 1, r);
    }
    #undef lc
    #undef rc
}sgt;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m >> q;
    rep(u, 1, n - 1) cin >> a[u] >> b[u + 1];
    rep(i, 1, m) {
        ll u, v, w;
        cin >> u >> v >> w;
        e[u].emplace_back(v + 1, w);
    }
    sgt.build(b, 1, 1, n);
    rep(u, 1, n) {
        for(auto [v, w] : e[u]) {
            sgt.modify(1, 1, n, 1, v - 1, w);
        }
        p[u] = a[u] + sgt.val[1];
    }
    sgt.build(p, 1, 1, n);
    cout << sgt.val[1] << endl;
    while(q--) {
        ll u, w;
        cin >> u >> w;
        sgt.modify(1, 1, n, u, u, -a[u]);
        a[u] = w;
        sgt.modify(1, 1, n, u, u, +a[u]);
        cout << sgt.val[1] << endl;
    }
    return 0;
}

标签:CF903G,min,题解,ll,modify,sgt,mid,Another,ql
From: https://www.cnblogs.com/ruierqwq/p/CF-903G.html

相关文章

  • CF1777D题解
    分析首先看到那个\(10^{100}\)再加上样例,我们就能意识到在不是特别多的操作次数后这颗树上的值就会全变成\(0\)。因为没有子节点在一次操作后显然就会变成\(0\),然后第一次叶节点就会变成\(0\),然后下一次子节点中只有叶节点的就会变成\(0\),以此类推,理论上最多操作\(n\)......
  • CF1878B题解
    CF1878BAleksaandStack题目翻译给定\(n\),试构造一个长度为\(n\)的严格上升正整数序列\(a_1,a_2,a_3,...,a_n\)使得\(\foralli\in[3,n],(a_{i-1}+a_{i-2})\nmid3a_i\)。单个测试点内包含多组测试数据。思路拿到题目,发现不好一个数一个数地构造,考虑......
  • 华科新生赛题解
    因为学校里面写代码的条件不足,比如教学楼里面使用键盘就会被盯着看。感觉有点点自闭。早知道退学了。不知道现在退学是不是算晚。昨天好兄弟车昱辉说你是在学习又不是在打游戏,但是我还是很羞涩。Abfs,需要把已经搜到的点在枚举1到n的时候去掉,所以可以使用并查集。或者链表......
  • CF1777C题解
    分析看到题面里面的子序列觉得很恶心,如果是子段感觉就会比较好做。如果直接填上子序列中间的空隙就可能会取一些比必须要取的数更大或者更小的数,影响我们的答案。那么就可以直接排序,使得子序列中间的空隙的数必然\(\geq\)左端且\(\leq\)右端,不会影响我们的答案(因为极差只......
  • [题解]CF1223F Stack Exterminable Arrays
    CCF出的原题观摩一下。思路首先可以用一个Trie来维护。在这里对本文中的一些变量做一下说明。\(p\)表示当前维护的Trie中,指向的元素编号。\(t_i\)表示在Trie中编号为\(i\)的元素在原序列中的值。\(f_i\)表示在Trie中编号为\(i\)的元素在Trie中的父......
  • CSP-S 2023 题解
    CSP-S2023题解游记打得非常烂。。。也是一个经验的总结吧:T1.密码锁(lock)似乎也没什么好讲的,直接模拟枚举每一种情况即可。放上我的考场代码。#include<bits/stdc++.h>usingnamespacestd;intn,a[10][8],b[2][90][8],ans=0,len,l;intread(){intx=0,f=1;char......
  • Codeforces 1862G 题解
    传送门题解因为有这个操作:将序列\(a\)加上\(\{n,n-1,\cdots,1\}\),考虑差分。那么显然每次操作会将差分数组中的每个元素减去\(1\),如果差分数组中有\(0\),就会把\(0\)删除。所以可以发现差分数组中剩下的一定是操作前的最大值。由于操作后最大值还是最大值,最小值仍......
  • CF1777A题解
    分析发现操作2不会改变数的奇偶性,故无视。那么操作就是单纯删一个数。对于一个连续出现\(x\)个奇偶性相同的数的序列,需要删\(x-1\)个数(因为只剩下一个数就不会和相邻的数奇偶性相同了)。觉得找序列太麻烦,观察到连续出现\(x\)个奇偶性相同的数的序列有\(x-1\)个不......
  • CF1523D Love-Hate 题解
    抽象化题意:一共有\(m\)个元素,给定\(n\)个集合,每个集合的元素不超过\(15\)个,求出一个元素个数最多的集合\(S\)是至少\(\lceil\dfrac{n}{2}\rceil\)个集合的子集。其中$p$$(1\len\le2\cdot10^5,1\lep\lem\le60)$我们先假设\(limit=\lceil\dfrac......
  • 2023级HAUT新生周赛题解汇总
    2023级HAUT新生周赛(零)熟悉周赛规则专场:2023级HAUT新生周赛(一)@21级学长专场(张子豪,张鑫,李昊阳):2023级HAUT新生周赛(二)@曹瑞峰专场:2023级HAUT新生周赛(三)@22级学姐专场(杨焱,刘振歌,周欣滢):2023级HAUT新生周赛(四)@牛浩然专场:2023级HAUT新生周赛(五)@陈兰锴专场:......