题目描述:

这是一道数据结构题。
我们拥有一个长度为n的数组a[i]。
我们有m次操作。操作有两种类型:
0 i val:表示我们要把a[i]修改为val;
1 l r k:表示我们要求出区间[l,r]的最多k个不相交子区间,并使得各个子区间的数的和尽量大,需要注意的是,我们也可以不选择区间,这时候数的和为0.
N,m不超过10^5.
所有的ai和val的绝对值均不超过500.k不超过20.询问的数目不超过10000.

  抛开k段先不管,假如要求连续一段的最大和,该怎么做?

  对于线段树的一段[L,R],要维护整段的sum(和),Lmax(从左开始的最大一段),Rmax(同上)以及max(最大的一段,任意的)



father_Lmax=MAX(lson_Lmax,lson_sum+rson_Rmax)

father_Rmax=MAX(rson_Rmax,rson_sum+lson_Rmax)

fahter_max=MAX(rson_max,lson_max,lson_rmax+rson_lmax)

至于具体证明……画个图就好了,很好理解的。

  假如是K段,那怎么破?

  只需要找出最大的一段,然后那段的每一个数乘上-1。做K次,累加每次的答案就好啦(答案是正的才累加,不然break掉)。

  一个数被选了两次,也就是不选。

附上代码:

change()是区间乘上-1

treeset是儿子更新父亲

fan()是翻转,乘上-1后,max=-1,min=-1,swap(max,min)

#include<cstdio>
#include<cmath>
#include<algorithm> #define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
#define lson (ro<<1)
#define rson (ro<<1|1) using namespace std; typedef long long ll; const int oo=1e9;
const int N=100000;
int T,n,d[N+10],m;
int ql[N+10],qr[N+10];
struct data { int sum,lmax,rmax,lmin,rmin,sw,zmax,zmin,xl,nl,xr,nr,nL,xL,nR,xR; } tree[N<<2],bcz; void fan(data &X)
{
X.sum=-X.sum;
X.lmin=-X.lmin; X.rmin=-X.rmin;
X.lmax=-X.lmax; X.rmax=-X.rmax;
X.zmax=-X.zmax; X.zmin=-X.zmin;
swap(X.lmin,X.lmax); swap(X.rmin,X.rmax);
swap(X.zmin,X.zmax); swap(X.nl,X.xl);
swap(X.nr,X.xr); swap(X.nL,X.xL); swap(X.nR,X.xR);
} void treeset(data &X,data &x1,data &x2,int L,int R)
{
int Mid=(L+R)>>1;
X.sum=x1.sum+x2.sum; X.zmax=x1.zmax; X.xL=x1.xL; X.xR=x1.xR;
if(X.zmax<x2.zmax)
{
X.zmax=x2.zmax;
X.xL=x2.xL; X.xR=x2.xR;
}
if(X.zmax<x1.rmax+x2.lmax)
{
X.zmax=x1.rmax+x2.lmax;
X.xL=x1.xr; X.xR=x2.xl;
} X.zmin=x1.zmin; X.nL=x1.nL; X.nR=x1.nR;
if(X.zmin>x2.zmin)
{
X.zmin=x2.zmin;
X.nL=x2.nL; X.nR=x2.nR;
}
if(X.zmin>x1.rmin+x2.lmin)
{
X.zmin=x1.rmin+x2.lmin;
X.nL=x1.nr; X.nR=x2.nl;
} X.lmin=x1.lmin; X.nl=x1.nl;
X.lmax=x1.lmax; X.xl=x1.xl;
X.rmin=x2.rmin; X.nr=x2.nr;
X.rmax=x2.rmax; X.xr=x2.xr;
if(x1.sum+x2.lmin<X.lmin)
{
X.lmin=x1.sum+x2.lmin;
X.nl=x2.nl;
}
if(x1.sum+x2.lmax>X.lmax)
{
X.lmax=x1.sum+x2.lmax;
X.xl=x2.xl;
}
if(x2.sum+x1.rmin<X.rmin)
{
X.rmin=x1.rmin+x2.sum;
X.nr=x1.nr;
}
if(x2.sum+x1.rmax>X.rmax)
{
X.rmax=x1.rmax+x2.sum;
X.xr=x1.xr;
}
} void down(int ro,int L,int R)
{
if(tree[ro].sw&1)
{
tree[ro].sw=0; tree[lson].sw++; tree[rson].sw++;
fan(tree[lson]); fan(tree[rson]);
}
} void build(int ro,int L,int R)
{
if(L==R)
{
tree[ro].sw=0; tree[ro].sum=d[L];
tree[ro].lmax=tree[ro].lmin=tree[ro].rmax=tree[ro].rmin=tree[ro].zmin=tree[ro].zmax=d[L];
tree[ro].xl=tree[ro].nl=tree[ro].xr=tree[ro].nr=tree[ro].nL=tree[ro].nR=tree[ro].xL=tree[ro].xR=L;
return;
}
int Mid=(L+R)>>1;
build(lson,L,Mid); build(rson,Mid+1,R);
treeset(tree[ro],tree[lson],tree[rson],L,R);
} void updata(int ro,int L,int R,int x,int val)
{
if(L>x || R<x) return;
if(L==x && R==x)
{
tree[ro].zmin=tree[ro].zmax=tree[ro].sum=val;
tree[ro].lmax=tree[ro].lmin=tree[ro].rmax=tree[ro].rmin=val;
return;
}
int Mid=(L+R)>>1;
down(ro,L,R);
updata(lson,L,Mid,x,val); updata(rson,Mid+1,R,x,val);
treeset(tree[ro],tree[lson],tree[rson],L,R);
} void change(int ro,int L,int R,int li,int ri)
{
if(L>ri || R<li) return;
if(li<=L && R<=ri)
{
tree[ro].sw++;
fan(tree[ro]); return;
}
int Mid=(L+R)>>1;
down(ro,L,R);
change(lson,L,Mid,li,ri); change(rson,Mid+1,R,li,ri);
treeset(tree[ro],tree[lson],tree[rson],L,R);
} data query(int ro,int L,int R,int li,int ri)
{
if(L>ri || R<li) return bcz;
if(li<=L && R<=ri) return tree[ro];
int Mid=(L+R)>>1;
down(ro,L,R);
data x1=query(lson,L,Mid,li,ri);
data x2=query(rson,Mid+1,R,li,ri);
if(x1.lmin!=oo && x2.lmin!=oo)
{
data X; treeset(X,x1,x2,L,R);
return X;
} else
if(x1.lmin!=oo) return x1; else return x2;
} int main()
{
freopen("2201.in","r",stdin);
freopen("2201.out","w",stdout);
scanf("%d",&T);
bcz.sum=0;
bcz.lmax=bcz.rmax=bcz.zmax=-oo;
bcz.lmin=bcz.rmin=bcz.zmin=oo;
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&d[i]);
scanf("%d",&m);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int w,a,b,k; scanf("%d%d%d",&w,&a,&b);
if(w==0) updata(1,1,n,a,b); else
if(w==1)
{
scanf("%d",&k); int ans=0,dw=0;
for(int i=1;i<=k;i++)
{
data get=query(1,1,n,a,b);
if(get.zmax>0) ans+=get.zmax; else break;
change(1,1,n,get.xL,get.xR);
ql[++dw]=get.xL; qr[dw]=get.xR;
}
printf("%d\n",ans);
for(int i=1;i<=dw;i++) change(1,1,n,ql[i],qr[i]);
}
}
}
return 0;
}

求区间连续不超过K段的最大和--线段树+大量代码的更多相关文章

  1. hihocoder#1046 K个串 可持久化线段树 + 堆

    首先考虑二分,然后发现不可行.... 注意到\(k\)十分小,尝试从这里突破 首先用扫描线来处理出以每个节点为右端点的区间的权值和,用可持久化线段树存下来 在所有的右端点相同的区间中,挑一个权值最大的 ...

  2. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  3. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

  4. 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树

    题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...

  5. BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

    之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...

  6. [POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]

    可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include &l ...

  7. bzoj 4504: K个串 可持久化线段树+堆

    题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...

  8. 【BZOJ4504】K个串 可持久化线段树+堆

    [BZOJ4504]K个串 Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计 ...

  9. BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)

    和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...

随机推荐

  1. 运维自动化-Ansible

    前言 天天说运维,究竟是干什么的?先看看工作流程呗.一般来说,运维工程师在一家企业里属于个位数的岗位,甚至只有一个.面对生产中NNN台服务器,NN个人员,工作量也是非常大的.所以嘛,图中的我好歹也会配 ...

  2. [XJOI]noip43 T2多人背包

    多人背包 DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包.这些包的容量是相同的,都是 V.可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值.在 DD 看来,合理的 ...

  3. c语言return与exit的区别

    2013-09-0918:54:33 exit函数在头文件stdlib.h中,函数原型: void exit(int status); exit(0) 正常运行程序并退出程序. exit(1) 非正常 ...

  4. css3实现3D切割轮播图案例

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. (转载)tnsping不是内部或外部命令

    手动添加 D:\app\Administrator\product\11.2.0\client_1\bin 到系统环境变量 path里面

  6. WinRAR 5.60 无广告正式版

    首先明确WinRAR唯一的官网是这个 https://www.rarlab.com/ 其余的都不要相信. 现在的问题是:不要脸的中国代理强行捆绑广告:即使你花钱注册同样要面对弹窗广告!这就不可接受了! ...

  7. -webkit-appearance: none; 去除浏览器默认样式

    -webkit-appearance: none;    去除浏览器默认样式

  8. Java泛型的一段代码

    package com.chase.test; import java.util.ArrayList; import java.util.Hashtable; import java.util.Lis ...

  9. 路飞学城Python-Day171

    Evernote Export 线性结构: python的列表操作 列表是如何存储的:顺序存储的,是一块连续的内存,内存是一堆格子,列表是一串连续的编号 32位机器上一个整数占4个字节 数组和列表有2 ...

  10. tomcat 配置 https 几点注意

    1.修改server.xml时候把注释的改改就好,不要添加,免得杂乱. 2.安装openssl openssl-devel autoconf libtool apr tomcat-native 才行. ...