题目描述:

这是一道数据结构题。
我们拥有一个长度为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. 实现model中的文件上传FTP(二)

    上一篇博客记录了如何将model中的图片存入FTP,通过一个第三方的storages简单的实现了,但是后续我发现如果想在浏览器通过url直接获取图片,就不太容易了(大神轻喷,小弟自学django和py ...

  2. 关于iscroll.js插件的使用

    iscroll 作用: 可以让区域滚动效果好看一些 使用: 1. html结构 外面必须包一层盒子,切内部的元素要尽量简单,不然会影响滚动效果 <div id="wrapper&quo ...

  3. 利用JavaScript实现文本框改文字功能

    <html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...

  4. intelij idea+springMVC+spring+mybatis 初探(持续更新)

    intelij idea+springMVC+spring+mybatis 初探(持续更新) intellij 创建java web项目(maven管理的SSH) http://blog.csdn.n ...

  5. LeetCode 42. Trapping Rain Water 【两种解法】(python排序遍历,C++ STL map存索引,时间复杂度O(nlogn))

    LeetCode 42. Trapping Rain Water Python解法 解题思路: 本思路需找到最高点左右遍历,时间复杂度O(nlogn),以下为向左遍历的过程. 将每一个点的高度和索引存 ...

  6. Arduino UNO R3

    Arduino 常见型号 当然还有 LilyPad,附图: 最常见的自然是UNO,最新版是第三版R3: 国内也有一些改进的板子.我用的是一般的板子,拿到货也只能默默了. 简介 The Uno is a ...

  7. aspnet_regiis加密文件提示路径中具有非法字符

    加密结果受当前目录影响,不知道是不是哪里操作错误,mark.   Web.config文件位置:E:\Web\Surgery 加密成功,上图命令最后有个".",表示web.conf ...

  8. VS2012 编译 boost1.53/ boost1.49

    原文链接:http://blog.csdn.net/ly131420/article/details/8904122 一.下载Boost库 boost_1_53_0.zip   (http://www ...

  9. 将电脑特定文件夹保存在U盘中

    为什么 各种网盘,借着国家扫黄的阶梯,纷纷取消自己的网盘的服务.但自己有一些不是很大,但又很重要的东西,比如说代码(虽然学的渣) 怎么做 再网上百度,有一些将U盘的文件偷偷拷到电脑的脚本,改一下复制文 ...

  10. (转)RabbitMQ学习之消息可靠性及特性

    http://blog.csdn.net/zhu_tianwei/article/details/53971296 下面主要从队列.消息发送.消息接收方面了解消息传递过的一些可靠性处理. 1.队列 消 ...