求区间连续不超过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> # ...
随机推荐
- SQL使用总结——集合操作函数
Oracle中集合操作符专门用于合并多条select 语句的结果,包括:UNION, UNION ALL, INTERSECT, MINUS.当使用集合操作符时,必须确保不同查询的列个数和数据类型匹配 ...
- intelij idea+springMVC+spring+mybatis 初探(持续更新)
intelij idea+springMVC+spring+mybatis 初探(持续更新) intellij 创建java web项目(maven管理的SSH) http://blog.csdn.n ...
- hdu 3729 最大匹配
此题是我AC的HDU的201道题目.泪流满面啊! 字典序最大(最小)真是个烦人的东西. 学生i与其对应的分数区间的每个点连一条边.字典序最大,编号最大的学生开始匹配. HK无法AC啊,试了很久.我不会 ...
- forEach 列出数组的每个元素:
数组.forEach便利所有的元素 array.forEach(function(currentValue, index, arr), thisValue) function(currentValue ...
- 路飞学城Python-Day75
1.什么是Django? Django是一个web框架,也是python中最火的一个框架,应用最多,内容最全 2.什么是web框架? python的一个脚本就是一个应用程序,web框架就是和前端有关系 ...
- 实验二:1、输出“Hello Word!”;2、测试主方法 的输入参数。3、总结
一.输出:“Hello Word!” 1.新建java项目:点击File->New->Java Project.在project name一栏中输入自己所要创建的项目名称,点击Finish ...
- web内置对象
内置对象,宿主对象,自定义对象的区别? 内置对象: 系统所提供的对象:Object,Array,Math,Date等等. 宿主对象: JS所运行的环境提 ...
- [luogu3627 APIO2009] 抢掠计划 (tarjan缩点+spfa最长路)
传送门 Description Input 第一行包含两个整数 N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表 ...
- jquery 去重
var yearArray = new Array(2009, 2009, 2010, 2010, 2009, 2010); $.unique(yearArray); alert(yearArray) ...
- Python-基础-day3
基础数据类型 1.什么是数据类型? 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大,但从某种角度上看又很傻,除非你明确的告诉它,1是数字,“汉”是文字,否则它是分不清1 ...