Advertisement
EntropyIncreaser

Kinetic SegTree: Range increment, query maxsum range

Feb 17th, 2020
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.21 KB | None | 0 0
  1. #include <cstdio>
  2.  
  3. #include <algorithm>
  4. #include <functional>
  5.  
  6. #define LOG(FMT...) fprintf(stderr, FMT)
  7.  
  8. using namespace std;
  9.  
  10. typedef long long ll;
  11.  
  12. struct Line {
  13.   int k;
  14.   ll b;
  15.  
  16.   Line() : k(0), b(0) {}
  17.  
  18.   Line(ll b) : k(0), b(b) {}
  19.  
  20.   Line(int k, ll b) : k(k), b(b) {}
  21.  
  22.   ll operator()(int x) const { return k * (ll)x + b; }
  23.  
  24.   Line operator+(const Line& rhs) const { return Line(k + rhs.k, b + rhs.b); }
  25.   Line operator-() const { return Line(-k, -b); }
  26.   Line operator-(const Line& rhs) const { return *this + (-rhs); }
  27.  
  28.   Line inc(ll x) const { return Line(k, b + k * (ll)x); }
  29. };
  30.  
  31. struct Node {
  32.   ll sum, x;
  33.   Line lmax, rmax, tmax;
  34.   int l, r;
  35.   ll cert;
  36.   Node *ls, *rs;
  37.  
  38.   int len() const { return r - l + 1; }
  39.  
  40.   ll gsum() const { return sum + x * len(); }
  41.  
  42.   ll gcert() const { return cert - x; }
  43.  
  44.   Line gsumLine() const { return Line(len(), sum).inc(x); }
  45.  
  46. #define DEFGET(V) Line g##V() const { return V.inc(x); }
  47.  
  48.   DEFGET(lmax)
  49.   DEFGET(rmax)
  50.   DEFGET(tmax)
  51. };
  52.  
  53. struct Tmp {
  54.   ll sum, lmax, rmax, tmax;
  55.  
  56.   Tmp(ll sum, ll lmax, ll rmax, ll tmax) : sum(sum), lmax(lmax), rmax(rmax), tmax(tmax) {}
  57.  
  58.   friend Tmp unite(const Tmp& lhs, const Tmp& rhs) {
  59.     return Tmp(lhs.sum + rhs.sum,
  60.                max(lhs.lmax, lhs.sum + rhs.lmax),
  61.                max(rhs.rmax, rhs.sum + lhs.rmax),
  62.                max({lhs.tmax, rhs.tmax, lhs.rmax + rhs.lmax}));
  63.   }
  64. };
  65.  
  66. const ll INF = 1LL << 60;
  67.  
  68. ll compete(const Line& delt, ll x) {
  69.   if (delt(x) > 0) {
  70.     if (delt.k < 0) {
  71.       ll chp = delt.b / -delt.k + 1;
  72.       if (chp <= INF)
  73.         return chp;
  74.     }
  75.   } else if (delt(x) < 0) {
  76.     if (delt.k > 0) {
  77.       ll chp = (-delt.b) / delt.k + 1;
  78.       if (chp <= INF)
  79.         return chp;
  80.     }
  81.   } else if (delt.k)
  82.     return x + 1;
  83.   return INF;
  84. }
  85.  
  86. void chkmin(ll& x, ll y) {
  87.   if (x > y) x = y;
  88. }
  89.  
  90. Line max(const Line& lhs, const Line& rhs, ll x) { return lhs(x) < rhs(x) ? rhs : lhs; }
  91.  
  92. struct KineticTournament {
  93.   Node* segTree;
  94.  
  95.   Node* build(int l, int r);
  96.  
  97.   KineticTournament(int n) : segTree(build(1, n)) {}
  98.  
  99.   void updateLeaf(Node* o) {
  100.     if (o->sum + o->x > 0) {
  101.       o->lmax = o->rmax = o->tmax = Line(1, o->sum);
  102.       o->cert = INF;
  103.     } else {
  104.       o->lmax = o->rmax = o->tmax = Line(0, 0);
  105.       o->cert = compete(Line(-1, -o->sum), o->x);
  106.     }
  107.   }
  108.  
  109.   void update(Node* o) {
  110.     o->sum = o->ls->gsum() + o->rs->gsum();
  111.     o->lmax = max(o->ls->glmax(), o->ls->gsumLine() + o->rs->glmax(), o->x);
  112.     o->rmax = max(o->rs->grmax(), o->rs->gsumLine() + o->ls->grmax(), o->x);
  113.     o->tmax = max(max(o->ls->gtmax(), o->rs->gtmax(), o->x), o->ls->grmax() + o->rs->glmax(), o->x);
  114.     o->cert = min({compete(o->lmax - o->ls->glmax(), o->x), compete(o->lmax - o->ls->gsumLine() - o->rs->glmax(), o->x),
  115.                    compete(o->rmax - o->rs->grmax(), o->x), compete(o->rmax - o->rs->gsumLine() - o->ls->grmax(), o->x),
  116.                    compete(o->tmax - o->ls->gtmax(), o->x), compete(o->tmax - o->rs->gtmax(), o->x),
  117.                    compete(o->tmax - o->ls->grmax() - o->rs->glmax(), o->x), o->ls->gcert(), o->rs->gcert()});
  118.   }
  119.  
  120.   void pushDown(Node* o) {
  121.     if (o->x) {
  122.       o->ls->x += o->x;
  123.       o->rs->x += o->x;
  124.       o->x = 0;
  125.     }
  126.   }
  127.  
  128.   void changeTraj(Node* o) {
  129.     if (o->cert > o->x) return;
  130.     if (o->l == o->r)
  131.       return updateLeaf(o);
  132.     pushDown(o);
  133.     changeTraj(o->ls);
  134.     changeTraj(o->rs);
  135.     update(o);
  136.   }
  137.  
  138.   void increase(Node* o, int l, int r, int x) {
  139.     if (o->l == l && o->r == r) {
  140.       o->x += x;
  141.       return changeTraj(o);
  142.     }
  143.     pushDown(o);
  144.     if (r <= o->ls->r)
  145.       increase(o->ls, l, r, x);
  146.     else if (l >= o->rs->l)
  147.       increase(o->rs, l, r, x);
  148.     else {
  149.       increase(o->ls, l, o->ls->r, x);
  150.       increase(o->rs, o->rs->l, r, x);
  151.     }
  152.     update(o);
  153.   }
  154.  
  155.   void increase(int l, int r, int x) {
  156.     increase(segTree, l, r, x);
  157.   }
  158.  
  159.   Tmp qry(Node* o, int l, int r) {
  160.     if (o->l == l && o->r == r)
  161.       return Tmp(o->gsum(), o->lmax(o->x), o->rmax(o->x), o->tmax(o->x));
  162.     pushDown(o);
  163.     Tmp ret(0, 0, 0, 0);
  164.     if (r <= o->ls->r)
  165.       ret = qry(o->ls, l, r);
  166.     else if (l >= o->rs->l)
  167.         ret = qry(o->rs, l, r);
  168.     else
  169.       ret = unite(qry(o->ls, l, o->ls->r), qry(o->rs, o->rs->l, r));
  170.     update(o);
  171.     return ret;
  172.   }
  173.  
  174.   ll qry(int l, int r) {
  175.     return qry(segTree, l, r).tmax;
  176.   }
  177. };
  178.  
  179. const int N = 100010;
  180.  
  181. int n, m;
  182. int a[N];
  183.  
  184. Node* KineticTournament::build(int l, int r) {
  185.   static Node pool[N * 2], *top = pool;
  186.   Node* p = top++;
  187.   p->l = l;
  188.   p->r = r;
  189.   if (l == r) {
  190.     p->sum = a[l];
  191.     updateLeaf(p);
  192.     return p;
  193.   }
  194.   int mid = (l + r) >> 1;
  195.   p->ls = build(l, mid);
  196.   p->rs = build(mid + 1, r);
  197.   update(p);
  198.   return p;
  199. }
  200.  
  201. int main() {
  202. //  freopen("test.in", "r", stdin);
  203. //  freopen("test.out", "w", stdout);
  204.   scanf("%d%d", &n, &m);
  205.   for (int i = 1; i <= n; ++i)
  206.     scanf("%d", &a[i]);
  207.   KineticTournament kt(n);
  208.   while (m--) {
  209.     int opt, l, r;
  210.     scanf("%d%d%d", &opt, &l, &r);
  211.     if (opt == 1) {
  212.       int x;
  213.       scanf("%d", &x);
  214.       if (x)
  215.         kt.increase(l, r, x);
  216.     } else
  217.       printf("%lld\n", kt.qry(l, r));
  218.   }
  219.   return 0;
  220. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement