题目链接:洛谷
题目大意:【题意翻译已经够直白了】
首先,相信大家一开始都是想去直接dp,但是发现复杂度不对。
于是我们考虑一个黑科技:模拟费用流(相信大部分人看见数据范围就绝对不会想到费用流)
我们考虑进行拆点,设i->i':(1,a[i]),i'->i+1:(1,0),而且总流量$leq k$,然后就跑最大费用最大流。
这显然会$T$成sb,不过这个图比较简单,我们可以考虑手玩一下。
然后就发现每次的增广路就是这个区间里的最大和的子段对应的路径,然后再把这个最大和的子段里面所有数取相反数(反向边)。
然后就可以用线段树维护,这个线段树需要以下操作。
1.单点修改
2.对于区间[l,r],先找出这个区间的最大和的子段,然后把这个子段取相反数。
不过码量让人想哭。。。(好不容易调出来,纪念一下。

1 #include<bits/stdc++.h> 2 #define Rint register int 3 using namespace std; 4 const int N = 100003; 5 struct Node { 6 int L, R, sum, maxv, maxl, maxr, minv, minl, minr, lmax, lmaxid, lmin, lminid, rmax, rmaxid, rmin, rminid; 7 bool rev; 8 inline Node(int pos = 0, int val = 0){ 9 L = R = maxl = maxr = minl = minr = lmaxid = lminid = rmaxid = rminid = pos; 10 sum = maxv = minv = lmax = lmin = rmax = rmin = val; 11 rev = false; 12 } 13 } seg[N << 2], q[22]; 14 inline Node merge(const Node &a, const Node &b){ 15 Node now; 16 now.L = a.L; now.R = b.R; 17 now.sum = a.sum + b.sum; 18 if(a.lmax >= a.sum + b.lmax) now.lmax = a.lmax, now.lmaxid = a.lmaxid; 19 else now.lmax = a.sum + b.lmax, now.lmaxid = b.lmaxid; 20 if(a.lmin <= a.sum + b.lmin) now.lmin = a.lmin, now.lminid = a.lminid; 21 else now.lmin = a.sum + b.lmin, now.lminid = b.lminid; 22 if(b.rmax >= b.sum + a.rmax) now.rmax = b.rmax, now.rmaxid = b.rmaxid; 23 else now.rmax = b.sum + a.rmax, now.rmaxid = a.rmaxid; 24 if(b.rmin <= b.sum + a.rmin) now.rmin = b.rmin, now.rminid = b.rminid; 25 else now.rmin = b.sum + a.rmin, now.rminid = a.rminid; 26 now.maxv = a.rmax + b.lmax; now.maxl = a.rmaxid; now.maxr = b.lmaxid; 27 if(now.maxv < a.maxv) now.maxv = a.maxv, now.maxl = a.maxl, now.maxr = a.maxr; 28 if(now.maxv < b.maxv) now.maxv = b.maxv, now.maxl = b.maxl, now.maxr = b.maxr; 29 now.minv = a.rmin + b.lmin; now.minl = a.rminid; now.minr = b.lminid; 30 if(now.minv > a.minv) now.minv = a.minv, now.minl = a.minl, now.minr = a.minr; 31 if(now.minv > b.minv) now.minv = b.minv, now.minl = b.minl, now.minr = b.minr; 32 now.rev = false; 33 return now; 34 } 35 inline void pushup(int x){seg[x] = merge(seg[x << 1], seg[x << 1 | 1]);} 36 inline void rev(Node &a){ 37 a.rev ^= 1; 38 a.sum = -a.sum; 39 swap(a.lmax, a.lmin); swap(a.lmaxid, a.lminid); 40 a.lmax = -a.lmax; a.lmin = -a.lmin; 41 swap(a.rmax, a.rmin); swap(a.rmaxid, a.rminid); 42 a.rmax = -a.rmax; a.rmin = -a.rmin; 43 swap(a.maxv, a.minv); swap(a.maxl, a.minl); swap(a.maxr, a.minr); 44 a.maxv = -a.maxv; a.minv = -a.minv; 45 } 46 inline void pushdown(int x){ 47 if(seg[x].rev){ 48 rev(seg[x << 1]); 49 rev(seg[x << 1 | 1]); 50 seg[x].rev = false; 51 } 52 } 53 int n, m, a[N]; 54 inline void build(int x, int L, int R){ 55 if(L == R){ 56 seg[x] = Node(L, a[L]); 57 return; 58 } 59 int mid = L + R >> 1; 60 build(x << 1, L, mid); 61 build(x << 1 | 1, mid + 1, R); 62 pushup(x); 63 } 64 inline void change(int x, int L, int R, int pos, int val){ 65 if(L == R){ 66 seg[x] = Node(L, val); 67 return; 68 } 69 int mid = L + R >> 1; 70 pushdown(x); 71 if(pos <= mid) change(x << 1, L, mid, pos, val); 72 else change(x << 1 | 1, mid + 1, R, pos, val); 73 pushup(x); 74 } 75 inline void modify(int x, int L, int R, int l, int r){ 76 if(l <= L && R <= r){ 77 rev(seg[x]); 78 return; 79 } 80 int mid = L + R >> 1; 81 pushdown(x); 82 if(l <= mid) modify(x << 1, L, mid, l, r); 83 if(mid < r) modify(x << 1 | 1, mid + 1, R, l, r); 84 pushup(x); 85 } 86 inline Node query(int x, int L, int R, int l, int r){ 87 if(l <= L && R <= r) return seg[x]; 88 int mid = L + R >> 1; 89 pushdown(x); 90 if(r <= mid) return query(x << 1, L, mid, l, r); 91 else if(mid < l) return query(x << 1 | 1, mid + 1, R, l, r); 92 else return merge(query(x << 1, L, mid, l, r), query(x << 1 | 1, mid + 1, R, l, r)); 93 } 94 //inline void dfs(int x, int L, int R){ 95 // if(L == R){ 96 // printf("%d ", seg[x].maxv); 97 // return; 98 // } 99 // int mid = L + R >> 1; 100 // pushdown(x); 101 // dfs(x << 1, L, mid); 102 // dfs(x << 1 | 1, mid + 1, R); 103 //} 104 int main(){ 105 scanf("%d", &n); 106 for(Rint i = 1;i <= n;i ++) scanf("%d", a + i); 107 build(1, 1, n); 108 scanf("%d", &m); 109 while(m --){ 110 int opt, x, y, k; 111 scanf("%d%d%d", &opt, &x, &y); 112 if(opt == 0) 113 change(1, 1, n, x, y); 114 else { 115 scanf("%d", &k); 116 int ans = 0, pos = k; 117 for(Rint i = 1;i <= k;i ++){ 118 q[i] = query(1, 1, n, x, y); 119 if(q[i].maxv <= 0){pos = i - 1; break;} 120 modify(1, 1, n, q[i].maxl, q[i].maxr); 121 // dfs(1, 1, n); puts(""); 122 ans += q[i].maxv; 123 } 124 for(Rint i = 1;i <= pos;i ++) modify(1, 1, n, q[i].maxl, q[i].maxr); 125 printf("%d ", ans); 126 } 127 } 128 }