Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- const ll nmax = 1e9+7;
- const ll nmax2 = 998244353;
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- #include <ext/pb_ds/detail/standard_policies.hpp>
- using namespace __gnu_pbds;
- typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
- typedef tree<std::pair<ll, ll>, null_type, less<std::pair<ll,ll>>, rb_tree_tag, tree_order_statistics_node_update> ordered_set_pair;
- struct mergesort_tree {
- ll n;
- struct node {
- std::vector<ll> container;
- std::vector<ll> prefix;
- ll low;
- ll high;
- };
- std::vector<node> tree;
- std::vector<ll> merge (std::vector<ll> &left, std::vector<ll> &right) {
- std::vector<ll> temp;
- ll l = 0, r = 0;
- while ((l != left.size()) || (r != right.size())){
- if (l == left.size()){
- temp.push_back(right[r++]);
- } else if (r == right.size()){
- temp.push_back(left[l++]);
- } else if (left[l] > right[r]) {
- temp.push_back(right[r++]);
- } else {
- temp.push_back(left[l++]);
- }
- }
- return temp;
- }
- std::vector<ll> pref_calc (std::vector<ll> &a) {
- std::vector<ll> temp;
- ll sum = 0;
- temp.push_back(sum);
- for (ll i = 0; i < a.size(); i++){
- sum += a[i];
- temp.push_back(sum);
- }
- return temp;
- }
- node combine(node n1, node n2){
- node n3;
- n3.container = merge(n1.container, n2.container);
- n3.prefix = pref_calc(n3.container);
- n3.high = std::max(n1.high, n2.high);
- n3.low = std::min(n1.low, n2.low);
- return n3;
- }
- mergesort_tree (const std::vector<ll> &a) {
- n = a.size();
- tree.resize(4 * n + 5);
- build_segment_tree(a, 1, 1, n);
- }
- void build_segment_tree (const std::vector<ll> &a, ll v, ll l, ll r){
- if (l == r){
- tree[v].low = a[l];
- tree[v].high = a[l];
- tree[v].container.push_back(a[l]);
- tree[v].prefix.push_back(0);
- tree[v].prefix.push_back(a[l]);
- return;
- }
- ll mid = (l + r) >> 1;
- build_segment_tree(a, 2 * v, l, mid);
- build_segment_tree(a, 2 * v + 1, mid + 1, r);
- tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- }
- ll range_query(ll v, ll l, ll r, ll tl, ll tr, ll val){
- if (l > r or r < tl or l > tr) return 0;
- if (tl <= l and r <= tr){
- if (tree[v].low > val) return 0;
- // std::cout << l << ' ' << r << '\\n';
- // std::cout << \"heres the container for this range => \\n\";
- // for (auto u: tree[v].container){
- // std::cout << u << ' ';
- // }
- // std::cout << '\\n';
- // std::cout << \"heres the prefix for this range => \\n\";
- // for (auto u: tree[v].prefix){
- // std::cout << u << ' ';
- // }
- // std::cout << '\\n';
- ll l_ = 1, r_ = tree[v].container.size();
- while (l_ < r_){
- ll mid_ = (l_ + r_ + 1) >> 1;
- if (tree[v].container[mid_ - 1] > val){
- r_ = mid_ - 1;
- } else {
- l_ = mid_;
- }
- }
- // std::cout << l_ << '\\n';
- return tree[v].prefix[l_];
- }
- ll mid = (l + r) >> 1;
- return range_query(2 * v, l, mid, tl, tr, val) + range_query(2 * v + 1, mid + 1, r, tl, tr, val);
- }
- ll range_query(ll l, ll r, ll val){
- return range_query(1, 1, n, l, r, val);
- }
- };
- template<class T>
- constexpr T power(T a, ll b){
- T res {1};
- for (; b; b /= 2, a *= a){
- if (b % 2){
- res *= a;
- }
- }
- return res;
- }
- constexpr ll mul(ll a, ll b, ll p) {
- ll res = a * b - (ll)(1.L * a * b / p) * p;
- res %= p;
- if (res < 0) {
- res += p;
- }
- return res;
- }
- template<ll P>
- struct modint {
- ll x;
- constexpr modint() : x {0} {}
- constexpr modint(ll y) : x {norm(y % getmod())} {}
- static ll mod;
- constexpr static ll getmod() {
- if (P > 0) {
- return P;
- } else {
- return mod;
- }
- }
- constexpr static void setmod(ll newmod) {
- mod = newmod;
- }
- constexpr ll norm(ll x) const {
- if (x < 0) {
- x += getmod();
- }
- if (x >= getmod()) {
- x -= getmod();
- }
- return x;
- }
- constexpr ll val() const {
- return x;
- }
- constexpr modint operator-() const {
- modint res;
- res.x = norm(getmod() - x);
- return res;
- }
- constexpr modint inv() const {
- return power(*this, getmod() - 2);
- }
- constexpr modint &operator*=(modint rhs) & {
- if (getmod() < (1ULL << 31)) {
- x = x * rhs.x % int(getmod());
- } else {
- x = mul(x, rhs.x, getmod());
- }
- return *this;
- }
- constexpr modint &operator+=(modint rhs) & {
- x = norm(x + rhs.x);
- return *this;
- }
- constexpr modint &operator-=(modint rhs) & {
- x = norm(x - rhs.x);
- return *this;
- }
- constexpr modint &operator/=(modint rhs) & {
- return *this *= rhs.inv();
- }
- friend constexpr modint operator*(modint lhs, modint rhs) {
- modint res = lhs;
- res *= rhs;
- return res;
- }
- friend constexpr modint operator+(modint lhs, modint rhs) {
- modint res = lhs;
- res += rhs;
- return res;
- }
- friend constexpr modint operator-(modint lhs, modint rhs) {
- modint res = lhs;
- res -= rhs;
- return res;
- }
- friend constexpr modint operator/(modint lhs, modint rhs) {
- modint res = lhs;
- res /= rhs;
- return res;
- }
- friend constexpr std::istream &operator>>(std::istream &is, modint &a) {
- ll v;
- is >> v;
- a = modint(v);
- return is;
- }
- friend constexpr std::ostream &operator<<(std::ostream &os, const modint &a) {
- return os << a.val();
- }
- friend constexpr bool operator==(modint lhs, modint rhs ){
- return lhs.val() == rhs.val();
- }
- friend constexpr bool operator!=(modint lhs, modint rhs) {
- return lhs.val() != rhs.val();
- }
- };
- template<>
- ll modint<0>::mod = 1e9;
- using mm = modint<0>;
- class DSU {
- public:
- std::vector<ll> f, siz;
- DSU(ll n) : f(n + 1), siz(n + 1, 1) {
- std::iota(f.begin() + 1, f.end(), 1);
- }
- ll leader(ll x) {
- while (x != f[x]) x = f[x] = f[f[x]];
- return x;
- }
- bool same(ll x, ll y) {
- return leader(x) == leader(y);
- }
- void merge(ll x, ll y) {
- x = leader(x);
- y = leader(y);
- if (x == y) return;
- siz[x] += siz[y];
- f[y] = x;
- }
- ll size(ll x) {
- return siz[leader(x)];
- }
- void print(ll n){
- std::cout << "first nodes => ";
- for (ll i = 1; i <= n; i++) std::cout << i << " \n"[i == n];
- std::cout << "leader nodes => ";
- for (ll i = 1; i <= n; i++) std::cout << leader(i) << " \n"[i == n];
- std::cout << "size components => ";
- for (ll i = 1; i <= n; i++) std::cout << siz[i] << " \n"[i == n];
- }
- };
- struct lazy_segment_tree {
- ll n;
- struct node {
- ll minimum;
- bool lazytag;
- };
- std::vector<node> tree;
- node combine(node n1, node n2) {
- node n3;
- n3.minimum = std::min(n1.minimum, n2.minimum);
- n3.lazytag = false;
- return n3;
- }
- lazy_segment_tree (const std::vector<ll> &a) {
- n = a.size();
- tree.resize(4 * n + 5);
- build_segment_tree(a, 1, 1, n);
- }
- void build_segment_tree(const std::vector<ll> &a, ll v, ll l, ll r) {
- if (l == r){
- tree[v].minimum = a[l];
- tree[v].lazytag = false;
- return;
- }
- ll mid = (l + r) >> 1;
- build_segment_tree(a, 2 * v, l, mid);
- build_segment_tree(a, 2 * v + 1, mid + 1, r);
- tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- }
- void lazypropogate(ll v, ll l, ll mid, ll r){
- tree[v].lazytag = false;
- ll extra = tree[v].minimum - std::min(tree[2 * v].minimum, tree[2 * v + 1].minimum);
- tree[2 * v].minimum += extra;
- tree[2 * v + 1].minimum += extra;
- tree[2 * v].lazytag = true;
- tree[2 * v + 1].lazytag = true;
- }
- void range_update(ll v, ll l, ll r, ll tl, ll tr, ll val) {
- if (l > r or r < tl or l > tr) return;
- if (tl <= l and r <= tr){
- tree[v].lazytag = true;
- tree[v].minimum += val;
- return ;
- }
- ll mid = (l + r) >> 1;
- if (tree[v].lazytag) lazypropogate(v, l, mid, r);
- range_update(2 * v, l, mid, tl, tr, val);
- range_update(2 * v + 1, mid + 1, r, tl, tr, val);
- tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- }
- void range_update(ll l, ll r, ll val) {
- range_update(1, 1, n, l, r, val);
- }
- ll range_query(ll v, ll l, ll r, ll tl, ll tr) {
- if (l > r or r < tl or l > tr) return LLONG_MAX;
- if (tl <= l and r <= tr) {
- return tree[v].minimum;
- }
- ll mid = (l + r) >> 1;
- if (tree[v].lazytag) lazypropogate(v, l, mid, r);
- return std::min(tree[2 * v].minimum, tree[2 * v + 1].minimum);
- }
- ll range_query(ll l, ll r){
- return range_query(1, 1, n, l, r);
- }
- void point_update(ll v, ll l, ll r, ll target, ll val) {
- if (l == r){
- tree[v].minimum += val;
- return;
- }
- ll mid = (l + r) >> 1;
- if (tree[v].lazytag) lazypropogate(v, l, mid, r);
- if (target <= mid) {
- point_update(2 * v, l, mid, target, val);
- } else {
- point_update(2 * v + 1, mid + 1, r, target, val);
- }
- tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- }
- void point_update(ll target, ll val) {
- point_update(1, 1, n, target, val);
- }
- };
- // struct segment_tree {
- // ll n;
- // struct node {
- // ll minimum;
- // };
- // std::vector<node> tree;
- // node combine(node n1, node n2) {
- // node n3;
- // n3.minimum = std::min(n1.minimum, n2.minimum);
- // return n3;
- // }
- // segment_tree (const std::vector<ll> &a) {
- // n = a.size();
- // tree.resize(4 * n + 5);
- // build_segment_tree(a, 1, 1, n);
- // }
- // void build_segment_tree(const std::vector<ll> &a, ll v, ll l, ll r){
- // if (l == r){
- // tree[v].minimum = a[l];
- // return;
- // }
- // ll mid = (l + r) >> 1;
- // build_segment_tree(a, 2 * v, l, mid);
- // build_segment_tree(a, 2 * v + 1, mid + 1, r);
- // tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- // }
- // ll range_query(ll v, ll l, ll r, ll tl, ll tr) {
- // if (l > r or r < tl or l > tr) return LLONG_MAX;
- // if (tl <= l and r <= tr) {
- // return tree[v].minimum;
- // }
- // ll mid = (l + r) >> 1;
- // return std::min(range_query(2 * v, l, mid, tl, tr), range_query(2 * v + 1, mid + 1, r, tl, tr));
- // }
- // ll range_query(ll l, ll r) {
- // return range_query(1, 1, n, l, r);
- // }
- // void point_update(ll v, ll l, ll r, ll target, ll val) {
- // if (l == r){
- // tree[v].minimum += val;
- // return;
- // }
- // ll mid = (l + r) >> 1;
- // if (target <= mid) {
- // point_update(2 * v, l, mid, target, val);
- // } else {
- // point_update(2 * v + 1, mid + 1, r, target, val);
- // }
- // tree[v] = combine(tree[2 * v], tree[2 * v + 1]);
- // }
- // void point_update(ll target, ll val) {
- // point_update(1, 1, n, target, val);
- // }
- // };
- void solve() {
- ll n, m, q;
- std::cin >> n >> m >> q;
- std::vector<ll> a(n), b(n);
- for (ll i = 1; i < n; i++){
- std::cin >> a[i] >> b[i];
- }
- std::vector<std::pair<ll, ll>> adj[n + 1];
- for (ll i = 1, x, y, z; i <= m; i++){
- std::cin >> x >> y >> z;
- adj[x].push_back({y, z});
- }
- std::vector<ll> c(n + 1);
- for (ll i = 1; i <= n; i++) c[i] = b[i - 1];
- lazy_segment_tree segtree(c);
- for (ll i = 1; i <= n; i++){
- if (i == 1){
- for (auto &[u, cost]: adj[i]) {
- segtree.range_update(1, u, cost);
- }
- } else {
- for (auto &[u, cost]: adj[i]) {
- segtree.range_update(u + 1, n, cost);
- }
- }
- }
- std::vector<ll> ans(n + 1);
- for (ll i = 1; i < n; i++) {
- ans[i] = a[i];
- }
- ans[1] += segtree.range_query(1, n);
- for (ll i = 2; i <= n; i++) {
- for (auto &[u, cost]: adj[i]) {
- segtree.range_update(u + 1, n, -cost);
- segtree.range_update(1, u, cost);
- }
- ans[i] += segtree.range_query(1, n);
- }
- lazy_segment_tree segtree2(ans);
- std::cout << segtree2.range_query(1, n) << '\n';
- for (ll i = 1, x, y; i <= q; i++){
- std::cin >> x >> y;
- segtree2.point_update(x, y - a[x]);
- a[x] = y;
- std::cout << segtree2.range_query(1, n) << '\n';
- }
- }
- void number_theory() {
- /*
- // only linear sieve
- */
- // ll lp[1000001];
- // std::vector<ll> prs;
- // for (ll i = 1; i < 1000001; i++) lp[i] = -1;
- // for (ll i = 2; i <= 1000000; i++){
- // if (lp[i] == -1){
- // lp[i] = i;
- // prs.push_back(i);
- // }
- // for (ll j = 0; i * prs[j] <= 1000000; j++){
- // lp[i * prs[j]] = prs[j];
- // if (lp[i] == prs[j]) break;
- // }
- // }
- /*
- // old number theory util funcs
- */
- // ll expo(ll x, ll y){
- // if (y == 0) return 1;
- // ll ans = expo(x, y / 2);
- // return (ans *= ans) *= (y % 2)*x + (!(y % 2));
- // }
- // ll binpow(ll x, ll y, ll z){
- // if (y == 0) return 1;
- // ll ans = binpow(x, y / 2, z);
- // return (((ans *= ans) %= z) *= (y % 2)*x + (!(y % 2))) %= z;
- // }
- // ll modinv(ll x, ll m){
- // return binpow(x, m-2, m);
- // }
- // ll phi(ll n){
- // ll result = n;
- // for (ll i = 2; i * i <= n; i++){
- // if (n % i == 0){
- // while (n % i == 0){
- // n /= i;
- // }
- // result -= result / i;
- // }
- // }
- // if (n > 1) result -= result / n;
- // return result;
- // }
- /*
- // mobius function + linear sieve
- */
- // std::function<ll(ll, ll)> gcd_ll = [&](ll x, ll y) {
- // return (y == 0) ? x : gcd_ll(y, x % y);
- // };
- // ll lp[100001], mf[100001];
- // std::vector<ll> prs;
- // lp[1] = 1;
- // mf[1] = 1;
- // for (ll i = 2; i <= 100000; i++){
- // if (lp[i] == 0){
- // lp[i] = i;
- // mf[i] = -1;
- // prs.push_back(i);
- // }
- // for (ll j = 0; i * prs[j] <= 100000; j++){
- // lp[i * prs[j]] = prs[j];
- // if (gcd_ll(i, prs[j]) == 1) mf[i * prs[j]] = mf[i] * mf[prs[j]];
- // else mf[i * prs[j]] = 0;
- // if (lp[i] == prs[j]) break;
- // }
- // }
- }
- void iterative_segment_tree() {
- ll n;
- std::cin >> n;
- ll a[n + 1];
- for (ll i = 1; i <= n; i++) std::cin >> a[i];
- ll tree_min[2 * n + 3], tree_max[2 * n + 3];
- for (ll i = 1; i <= n; i++){
- tree_min[n + i - 1] = a[i];
- tree_max[n + i - 1] = a[i];
- }
- for (ll i = n - 1; i > 0; i--){
- tree_min[i] = std::min(tree_min[i << 1], tree_min[i << 1 | 1]);
- tree_max[i] = std::max(tree_max[i << 1], tree_max[i << 1 | 1]);
- }
- auto query_min = [&] (ll l_, ll r_) -> ll {
- ll res = LLONG_MAX;
- for (l_ += n - 1, r_ += n - 1; l_ < r_; l_ >>= 1, r_ >>= 1){
- if (l_&1) res = std::min(res, tree_min[l_++]);
- if (r_&1) res = std::min(res, tree_min[--r_]);
- }
- return res;
- };
- auto query_max = [&] (ll l_, ll r_) -> ll {
- ll res = 0;
- for (l_ += n - 1, r_ += n - 1; l_ < r_; l_ >>= 1, r_ >>= 1){
- if (l_&1) res = std::max(res, tree_max[l_++]);
- if (r_&1) res = std::max(res, tree_max[--r_]);
- }
- return res;
- };
- }
- int main(){
- std::ios_base::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- int t = 1;
- // std::cin >> t;
- while(t--) {
- solve();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement