首页 > 其他分享 >CF280D k-Maximum Subsequence Sum

CF280D k-Maximum Subsequence Sum

时间:2023-01-14 14:22:48浏览次数:48  
标签:int res Sum Maximum Subsequence tag msg val2 sum

CF280D k-Maximum Subsequence Sum

WC现在正在讲网络流,我也来写一题网络流!

一开始真想不到这题能费用流。但是 \(k\) 规模较小告诉我们可以先从一个一个区间贪心做入手。但是纯贪心一定是不对的,所以可以考虑反悔贪心(我觉得这题反悔贪心思路可能还要更简单一点?)。从费用流角度可以更好地描述反悔贪心的思路。

连边 \(i \rightarrow i + 1\),流了这条边就表示选 \(i\) 这个点,然后最大费用最大流就是答案。

直接上线段树模拟找增广路,需要维护单点修改,区间乘 \(-1\),区间最大子段和。

这就比较复杂了,建议想明白再写,正负需要分别维护,还要维护最大字段和的端点,我一个节点维护了 16 个值。

写了好长。

#include <cstdio>
#include <iostream>

#define int long long

using std::swap;

namespace IO {
  #define isdigit(x) (x >= '0' && x <= '9')
  template<typename T>
  inline void read(T &x) {
    x = 0; char ch = getchar(); int f = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if(f) x = -x;
  }
  template<typename T>
  inline void write(T x) {
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
  }
  #undef isdigit
}
using namespace IO;

const int N = 1e5 + 10;
const int inf = 1e15;
int n, a[N];

struct Msg { 
  int val1, lmx1, rmx1, lp1, rp1, pre1, suf1, val2, lmx2, rmx2, lp2, rp2, pre2, suf2, sum;
  inline Msg operator + (const Msg y) const{
    Msg res{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    res.sum = sum + y.sum;
    
    if(lmx1 > sum + y.lmx1) {
      res.pre1 = pre1;
      res.lmx1 = lmx1;
    } else {
      res.pre1 = y.pre1;
      res.lmx1 = sum + y.lmx1;
    }

    if(y.rmx1 > y.sum + rmx1) {
      res.suf1 = y.suf1;
      res.rmx1 = y.rmx1;
    } else {
      res.suf1 = suf1;
      res.rmx1 = y.sum + rmx1;
    }

    res.lp1 = suf1, res.rp1 = y.pre1;
    res.val1 = rmx1 + y.lmx1;
    if(res.val1 < val1) 
      res.val1 = val1, res.lp1 = lp1, res.rp1 = rp1;
    if(res.val1 < y.val1)
      res.val1 = y.val1, res.lp1 = y.lp1, res.rp1 = y.rp1;


    if(lmx2 > -sum + y.lmx2) {
      res.pre2 = pre2;
      res.lmx2 = lmx2;
    } else {
      res.pre2 = y.pre2;
      res.lmx2 = -sum + y.lmx2;
    }

    if(y.rmx2 > -y.sum + rmx2) {
      res.suf2 = y.suf2;
      res.rmx2 = y.rmx2;
    } else {
      res.suf2 = suf2;
      res.rmx2 = -y.sum + rmx2;
    }

    res.lp2 = suf2, res.rp2 = y.pre2;
    res.val2 = rmx2 + y.lmx2;
    if(res.val2 < val2) 
      res.val2 = val2, res.lp2 = lp2, res.rp2 = rp2;
    if(res.val2 < y.val2)
      res.val2 = y.val2, res.lp2 = y.lp2, res.rp2 = y.rp2;
    return res;
  }
}msg[N << 2];

struct Tag {
  int tp;
  inline void apply(Msg &t) const{
    if(tp) {
      t.sum = -t.sum;
      swap(t.lmx1, t.lmx2), swap(t.rmx1, t.rmx2);
      swap(t.pre1, t.pre2), swap(t.suf1, t.suf2);
      swap(t.lp1, t.lp2), swap(t.rp1, t.rp2);
      swap(t.val1, t.val2);
    }
  }
}tag[N << 2];

struct tri{
  int a, b, c;
  inline bool operator < (const tri y) {
    return a < y.a;
  }
};

inline tri max(tri x, tri y) {return y < x ? x : y;}

struct SegTree {
  #define lc (k << 1)
  #define rc (k << 1 | 1)
  #define mid ((l + r) >> 1)

  inline void pushdown(int k) {
    tag[k].apply(msg[lc]), tag[k].apply(msg[rc]);
    tag[lc].tp ^= tag[k].tp, tag[rc].tp ^= tag[k].tp;
    tag[k].tp = 0;
  }

  inline void build(int k, int l, int r) {
    if(l == r) {
      tag[k] = (Tag){0};
      if(a[l] < 0) tag[k] = (Tag){1}, a[l] = -a[l];
      msg[k] = Msg{a[l], a[l], a[l], l, l, l, l, 0, 0, 0, l, l - 1, l - 1, l + 1, a[l]};
      tag[k].apply(msg[k]);
      return;
    }
    build(lc, l, mid), build(rc, mid + 1, r);
    msg[k] = msg[lc] + msg[rc];
  }

  inline void modify(int k, int l, int r, int pos, int v) {
    if(l > pos || r < pos) return;
    if(l == r) {
      tag[k].tp = 0;
      if(v < 0) tag[k] = (Tag){1}, v = -v;
      msg[k] = Msg{v, v, v, l, l, l, l, 0, 0, 0, l, l - 1, l - 1, l + 1, v};
      tag[k].apply(msg[k]);
      return;
    }
    pushdown(k);
    modify(lc, l, mid, pos, v), modify(rc, mid + 1, r, pos, v);
    msg[k] = msg[lc] + msg[rc];
  }

  inline void mul(int k, int l, int r, int L, int R) {
    if(r < L || R < l) return;
    if(L <= l && r <= R) {
      Tag tmp{1};
      tmp.apply(msg[k]);
      tag[k].tp ^= -1;
      return;
    }
    pushdown(k);
    mul(lc, l, mid, L, R);
    mul(rc, mid + 1, r, L, R);
    msg[k] = msg[lc] + msg[rc];
  }

  inline Msg query(int k, int l, int r, int L, int R) {
    if(r < L || R < l) return Msg{-inf, -inf, -inf, 0, 0, 0, 0, -inf, -inf, -inf, 0, 0, 0, 0, 0};
    if(L <= l && r <= R) return msg[k];
    pushdown(k);
    return query(lc, l, mid, L, R) + query(rc, mid + 1, r, L, R);
  }
}seg;

Msg stk[N];
int top;

signed main() {
  read(n);
  for(int i = 1; i <= n; ++i)
    read(a[i]);
  seg.build(1, 1, n);
  int m = 0; read(m);
  for(int i = 1, tp, x, y, z; i <= m; ++i) {
    read(tp);
    if(!tp) {
      read(x), read(y);
      seg.modify(1, 1, n, x, y);
    }
    else {
      read(x), read(y), read(z);
      int sum = 0;
      while(z--) {
        Msg res = seg.query(1, 1, n, x, y);
        stk[++top] = res;
        sum += res.val1;
        seg.mul(1, 1, n, res.lp1, res.rp1);
      }
      printf("%lld\n",sum);
      while(top) seg.mul(1, 1, n, stk[top].lp1, stk[top].rp1), --top;
    }
  }
  return 0;
}

标签:int,res,Sum,Maximum,Subsequence,tag,msg,val2,sum
From: https://www.cnblogs.com/DCH233/p/17051734.html

相关文章

  • SPOJ LCMSUM 题解
    LCMSUM题意:求:\(\sum\limits_{i=1}^n\lim(i,n)\)数据范围:\(1\leqT\leq3\times10^5\),\(1\leqn\leq10^6\)。原式\(=\sum\limits_{i=1}^n\frac{i\timesn}{\gc......
  • [LeetCode] 2281. Sum of Total Strength of Wizards
    Astherulerofakingdom,youhaveanarmyofwizardsatyourcommand.Youaregivena 0-indexed integerarray strength,where strength[i] denotesthest......
  • Codeforces Round #713 (Div. 3) E. Permutation by Sum(贪心)
    本来手痒想自己开把div3练手来着,佬儿叫住我组队打,就换了这场,听说除了G数学,F也是模拟,其它的都是大模拟:)模拟人可以狠狠冲,注意细节即可https://codeforces.com/contest/......
  • Summernote 图片上传
    Summernote默认是插入Base64格式的图片,图片并没有上传到服务器。可以通过API自行实现,官方文档:https://summernote.org/deep-dive/#insertnode插入图片://@param{......
  • PowerUsageSummary.java源码分析
    在在线网站http://androidxref.com/上对Android版本6.0.1_r10源码进行分析官方手机的应用耗电排行具体实现位置在:/packages/apps/Settings/src/com/android/settings/fuel......
  • Maximum Number of Points From Grid Queries
    MaximumNumberofPointsFromGridQueriesYouaregivenan$m\timesn$integermatrix grid andanarray queries ofsize $k$.Findanarray answer ofs......
  • SUM和IF使用求部分和
    GROUPBY可以按照某一列的不同值进行分组,然后将不同组的数据可以利用聚合函数进行汇总取值。--我们可以在老师表里面求解不同班级的老师分别有多少名SELECTclass_id,COU......
  • 15. 3Sum [Medium]
    3SumGivenanintegerarraynums,returnallthetriplets[nums[i],nums[j],nums[k]]suchthati!=j,i!=k,andj!=k,andnums[i]+nums[j]+nums[k]==......
  • asm:segment -- assume:ds关联多个段(win_intel)
    asm:segment--assume:ds关联多个段(win_intel)    一、assume:ds关联多个段:程序源码 1;file_name=address.asm23456assumeds:datas......
  • 「解题报告」CF1442D Sum
    首先可以发现,如果我们选了两堆且两堆均没选完,那么如果我们将较小的一个改成选较大的一个的下一个,这样一直选一定是更优的,最后肯定会使一些堆全部选完,一些堆没选,一个堆选了......