求区间连续不超过K段的最大和--线段树+大量代码
题目描述:
这是一道数据结构题。
我们拥有一个长度为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段的最大和--线段树+大量代码的更多相关文章
- hihocoder#1046 K个串 可持久化线段树 + 堆
首先考虑二分,然后发现不可行.... 注意到\(k\)十分小,尝试从这里突破 首先用扫描线来处理出以每个节点为右端点的区间的权值和,用可持久化线段树存下来 在所有的右端点相同的区间中,挑一个权值最大的 ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- BZOJ 3065 带插入区间K小值(sag套线段树)
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 4696 Solved: 1527[Submit][Status][Di ...
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树
之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...
- [POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]
可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include &l ...
- bzoj 4504: K个串 可持久化线段树+堆
题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...
- 【BZOJ4504】K个串 可持久化线段树+堆
[BZOJ4504]K个串 Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计 ...
- BZOJ 3110 [ZJOI2013]K大数查询 (整体二分+线段树)
和dynamic rankings这道题的思想一样 只不过是把树状数组换成线段树区间修改,求第$K$大的而不是第$K$小的 这道题还有负数,需要离散 #include <vector> # ...
随机推荐
- JavaScript 面向对象(随笔)
构造函数创建对象 1构造函数是用new创建对象时调用的函数,与普通唯一的区别是构造函数名应该首字母大写. function Person() { this.age = 50; } let a = ne ...
- 实现model中的文件上传FTP(二)
上一篇博客记录了如何将model中的图片存入FTP,通过一个第三方的storages简单的实现了,但是后续我发现如果想在浏览器通过url直接获取图片,就不太容易了(大神轻喷,小弟自学django和py ...
- android随手记
Linearlayout: gravity:本元素中所有子元素的重力方向 layout_gravity:本元素对于父元素的重力方向 自定义权限:http://www.cnblogs.com/i ...
- CorelDRAW X7中相机滤镜呈现出的复古照片效果
CorelDRAW X7软件中相机效果滤镜较之以前版本又增添了许多功能,模拟各种“相机”镜头产生的效果,包括彩色.相片过滤器.棕褐色色调和时间器效果,可以让照片回到历史,展示过去流行的摄影风格.以下步 ...
- Nginx的安装与升级
1,构建Nginx服务器; 2.升级版本; 一, 构建Nginx服务器 1.使用源码包安装nginx软件包 # yum -y install gcc pcre-devel openssl-devel ...
- java真实面试题(2)
1,递归算法的实行过程,一般来说,可以分为()和()两个阶段,若一个问题的求解既可以用递归也可以用递推时,则往往用(),因为().贪婪法是一种()的算法. 答:递归算法分为递推和回归两个阶段,递推效率 ...
- JS 20180415作业
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- java调用第三方命令,process.waitfor()挂起(你不知道的坑)
我们常在java中运行第三方程序,如sh.python,java提供一个Runtime.exec()方法,生成一个Process对象.今天在使用这个方法的时候,发现接口半天没有返回数据.查了一下,原来 ...
- 洛谷P1563 玩具谜题 简单模拟
没意义,注意方向别判错. Code: #include<cstdio> #include<cstring> using namespace std; const int max ...
- linux 结构需要清理 (structure needs cleaning)
下面操作会删除挂载点所有文件,注意备份. df -T 查看出错的挂载点对应的文件系统和文件系统类型 然后umount这个文件系统 umount /dev/sda1 然后文件系统类型不同操作不同 ...