# CF280D k-Maximum Subsequence Sum (线段树)

10W个数10W个操作，操作有两种：

k最大为20

step 1，找到一条费用最大的增广路L

step 2，若找不到增广路，或L已经是负费用了，goto step 4，否则计算新费用，

step 3，删除L，在残量图中加入与L方向相反，费用相反的反向弧，goto step 1

step 4，输出答案

step 1，找到[L,R]中的一段最大连续和[l,r]

step 2，若sum[l,r]>0，将sum[l,r]计入答案，否则goto step 4

step 3，将[l,r]的所有数字取反，goto step 1

step 4，输出答案

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N = 101000;
struct Line {
int l,r,s;
Line(int l=0,int r=0,int s=0):l(l),r(r),s(s) {}
Line operator + (Line tt) {
return Line(l,tt.r,s+tt.s);
}
bool operator < (const Line &tt) const {
return s<tt.s;
}
void show() { printf("::%d %d %d\n",l,r,s); }
};
struct Node {
Line Lmax,Lmin,Rmax,Rmin,Vmax,Vmin,V;
int rev;
Node(int l=0,int r=0,int s=0) {
Lmax = Lmin = Rmax = Rmin = Vmax = Vmin = V = Line(l,r,s);
rev = 0;
}
void up(Node a,Node b) {
if (a.Lmax.l==0) { *this = b; return; }
Lmax = max(a.Lmax,a.V+b.Lmax);
Lmin = min(a.Lmin,a.V+b.Lmin);
Rmax = max(a.Rmax+b.V,b.Rmax);
Rmin = min(a.Rmin+b.V,b.Rmin);
Vmax = max(a.Rmax,b.Lmax);
Vmax = max(Vmax,max(a.Vmax,b.Vmax));
Vmax = max(Vmax,a.Rmax+b.Lmax);
Vmax = max(Vmax,max(Lmax,Rmax));
Vmin = min(a.Rmin,b.Lmin);
Vmin = min(Vmin,min(a.Vmin,b.Vmin));
Vmin = min(Vmin,a.Rmin+b.Lmin);
Vmin = min(Vmin,min(Lmin,Rmin));
V = a.V+b.V;
}
};
Node tree[N<<2];
int n,m;
void rev(int rt) {
Node &x = tree[rt];
x.rev ^= 1;
swap(x.Lmin,x.Lmax); swap(x.Rmin,x.Rmax); swap(x.Vmin,x.Vmax);
x.Lmin.s *= -1; x.Lmax.s *= -1; x.Rmin.s *= -1; x.Rmax.s *= -1;
x.Vmin.s *= -1; x.Vmax.s *= -1; x.V.s *= -1;
}
void down(int rt) {
if (tree[rt].rev) {
rev(rt<<1);
rev(rt<<1|1);
tree[rt].rev = 0;
}
}
void build(int l,int r,int rt) {
if (l==r) {
int val; scanf("%d",&val);
tree[rt] = Node(l,r,val);
return ;
}
int mid = l+r>>1;
build(lson);
build(rson);
tree[rt].up(tree[rt<<1],tree[rt<<1|1]);
}
void modify(int p,int v,int l,int r,int rt) {
if (l==r) {
tree[rt] = Node(l,r,v); return ;
}
int mid = l+r>>1;
down(rt);
if (p<=mid) modify(p,v,lson);
else modify(p,v,rson);
tree[rt].up(tree[rt<<1],tree[rt<<1|1]);
}
void rev(int L,int R,int l,int r,int rt) {
if (L<=l && r<=R) {
rev(rt); return ;
}
int mid = l+r>>1;
down(rt);
if (L<=mid) rev(L,R,lson);
if (mid< R) rev(L,R,rson);
tree[rt].up(tree[rt<<1],tree[rt<<1|1]);
}
Node query(int L,int R,int l,int r,int rt) {
if (L<=l && r<=R) return tree[rt];
int mid = l+r>>1;
down(rt);
Node ret;
if (L<=mid) ret.up(ret,query(L,R,lson));
if (R> mid) ret.up(ret,query(L,R,rson));
return ret;
}
int main() {
scanf("%d",&n);
build(1,n,1);
scanf("%d",&m);
while (m--) {
int op;
scanf("%d",&op);
if (op==0) {
int p,v;
scanf("%d%d",&p,&v);
modify(p,v,1,n,1);
} else {
int l,r,k,ans = 0;
scanf("%d%d%d",&l,&r,&k);
vector<Line> zxc;
for (int i = 0; i < k; i ++) {
Line t = query(l,r,1,n,1).Vmax;
zxc.push_back(t);
rev(t.l,t.r,1,n,1);
if (t.s>0) ans += t.s;
else break;
}
for (int i = 0; i < (int)zxc.size(); i ++)
rev(zxc[i].l,zxc[i].r,1,n,1);
printf("%d\n",ans);
}
}
return 0;
}