Description
给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少。
Input
The first line contains integer n (1 ≤ n ≤ 105), showing how many numbers the sequence has. The next line contains n integers a1, a2, …, an (|ai| ≤ 500).
The third line contains integer m (1 ≤ m ≤ 105) — the number of queries. The next m lines contain the queries in the format, given in the statement.
All changing queries fit into limits: 1 ≤ i ≤ n, |val| ≤ 500.
All queries to count the maximum sum of at most k non-intersecting subsegments fit into limits: 1 ≤ l ≤ r ≤ n, 1 ≤ k ≤ 20. It is guaranteed that the number of the queries to count the maximum sum of at most k non-intersecting subsegments doesn’t exceed 10000.
Output
For each query to count the maximum sum of at most k non-intersecting subsegments print the reply — the maximum sum. Print the answers to the queries in the order, in which the queries follow in the input.
Sample Input
9 -8 9 -1 -1 -1 9 -8 9
3
1 1 9 1
1 1 9 2
1 4 6 3
Sample Output
25
0
HINT
In the first query of the first example you can select a single pair (1, 9). So the described sum will be 17.
Look at the second query of the first example. How to choose two subsegments? (1, 3) and (7, 9)? Definitely not, the sum we could get from (1, 3) and (7, 9) is 20, against the optimal configuration (1, 7) and (9, 9) with 25.The answer to the third query is 0, we prefer select nothing if all of the numbers in the given interval are negative.
Source
分析:
详尽题解
费用流的构图,线段树手动模拟增广过程
线段树维护方法:
维护一段区间的最大子序列
每次我们提取出一个最大子序列时,我们要把这个子序列取反(*-1,防止重复选择),所以还需要维护最小子序列
每进行一次取反,当前最大和子序列一定变成最小和子序列,最小和子序列一定变成最大,那么直接swap一下就可以了
鉴于一次询问需要增广K次,每一次都要要取反,所以需要开一个栈记录一下当前询问所反转的所有区间,在结束时还原
总的时间复杂度是 O(knlogn) O ( k n l o g n )
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100010;
struct node{
int lx,rx,mx,sum;
int lp,rp,p1,p2;
void init(int l,int val) {
lp=rp=p1=p2=l;
lx=rx=mx=sum=val;
}
};
struct Tree{
int l,r;
bool flag;
node mn,mx;
void init(int val) {
mx.init(l,val);
mn.init(l,-val);
}
};
Tree t[N<<2];
int n,m,a[N];
node merge(node a,node b) {
node t;
t.sum=a.sum+b.sum;
t.lx=a.lx; t.lp=a.lp;
if (a.sum+b.lx>t.lx) t.lx=a.sum+b.lx,t.lp=b.lp;
t.rx=b.rx; t.rp=b.rp;
if (b.sum+a.rx>t.rx) t.rx=b.sum+a.rx,t.rp=a.rp;
t.mx=a.rx+b.lx; t.p1=a.rp; t.p2=b.lp;
if (a.mx>t.mx) t.mx=a.mx,t.p1=a.p1,t.p2=a.p2;
if (b.mx>t.mx) t.mx=b.mx,t.p1=b.p1,t.p2=b.p2;
return t;
}
void update(int bh) {
t[bh].mn=merge(t[bh<<1].mn,t[bh<<1|1].mn);
t[bh].mx=merge(t[bh<<1].mx,t[bh<<1|1].mx);
}
void push(int bh) {
if (t[bh].l==t[bh].r) return;
if (t[bh].flag) {
swap(t[bh<<1].mn,t[bh<<1].mx);
swap(t[bh<<1|1].mn,t[bh<<1|1].mx);
t[bh<<1].flag^=1; t[bh<<1|1].flag^=1;
t[bh].flag^=1;
}
}
void build(int bh,int l,int r) {
t[bh].l=l; t[bh].r=r;
if (l==r) {
t[bh].init(a[l]);
return;
}
int mid=(l+r)>>1;
build(bh<<1,l,mid);
build(bh<<1|1,mid+1,r);
update(bh);
}
void change(int bh,int pos,int z) {
push(bh);
int l=t[bh].l,r=t[bh].r,mid=(l+r)>>1;
if (l==r) {
t[bh].init(z);
return;
}
if (pos<=mid) change(bh<<1,pos,z);
else change(bh<<1|1,pos,z);
update(bh);
}
void reverse(int bh,int L,int R) {
push(bh);
int l=t[bh].l,r=t[bh].r,mid=(l+r)>>1;
if (l>=L&&r<=R) {
swap(t[bh].mn,t[bh].mx);
t[bh].flag^=1;
return;
}
if (L<=mid) reverse(bh<<1,L,R);
if (R>mid) reverse(bh<<1|1,L,R);
update(bh);
}
node ask(int bh,int L,int R) {
push(bh);
int l=t[bh].l,r=t[bh].r,mid=(l+r)>>1;
if (l>=L&&r<=R) return t[bh].mx;
if (R<=mid) return ask(bh<<1,L,R);
else if (L>mid) return ask(bh<<1|1,L,R);
else return merge(ask(bh<<1,L,mid),ask(bh<<1|1,mid+1,R));
}
struct point{
int x,y;
};
point q[N];
int top;
void solve(int l,int r,int x) {
top=0;
int ans=0;
while (x--) {
node t=ask(1,l,r);
if (t.mx>0) ans+=t.mx;
else break;
reverse(1,t.p1,t.p2);
top++;
q[top].x=t.p1; q[top].y=t.p2;
}
printf("%d\n",ans);
for (int i=top;i>0;i--)
reverse(1,q[i].x,q[i].y);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
int opt,l,r,x;
while (m--) {
scanf("%d",&opt);
if (opt==1) {
scanf("%d%d%d",&l,&r,&x);
solve(l,r,x);
}
else {
scanf("%d%d",&l,&x);
change(1,l,x);
}
}
return 0;
}