传送门

线段树经典题目。


每次先找到最大子段和来更新答案,然后利用网络流反悔退流的思想把这个最大字段乘-1之后放回去。

代码:

  1. #include<bits/stdc++.h>
  2. #define N 100005
  3. #define lc (p<<1)
  4. #define rc (p<<1|1)
  5. #define mid (T[p].l+T[p].r>>1)
  6. using namespace std;
  7. inline int read(){
  8. int ans=0,w=1;
  9. char ch=getchar();
  10. while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
  11. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  12. return ans*w;
  13. }
  14. int n,m,a[N],ans=0;
  15. struct node{int l,r,lmx,rmx,mmx,sum,lmn,rmn,mmn,lmxp,lmnp,rmxp,rmnp,mxl,mxr,mnl,mnr,tag;}T[N<<2];
  16. inline int max(int a,int b){return a>b?a:b;}
  17. inline int min(int a,int b){return a<b?a:b;}
  18. inline node operator+(node a,node b){
  19. node ret;
  20. ret.sum=a.sum+b.sum,ret.l=a.l,ret.r=b.r;
  21. if(a.lmx>a.sum+b.lmx)ret.lmx=a.lmx,ret.lmxp=a.lmxp;
  22. else ret.lmx=a.sum+b.lmx,ret.lmxp=b.lmxp;
  23. if(a.lmn<a.sum+b.lmn)ret.lmn=a.lmn,ret.lmnp=a.lmnp;
  24. else ret.lmn=a.sum+b.lmn,ret.lmnp=b.lmnp;
  25. if(b.rmx>b.sum+a.rmx)ret.rmx=b.rmx,ret.rmxp=b.rmxp;
  26. else ret.rmx=b.sum+a.rmx,ret.rmxp=a.rmxp;
  27. if(b.rmn<b.sum+a.rmn)ret.rmn=b.rmn,ret.rmnp=b.rmnp;
  28. else ret.rmn=b.sum+a.rmn,ret.rmnp=a.rmnp;
  29. ret.mmx=a.mmx,ret.mxl=a.mxl,ret.mxr=a.mxr;
  30. if(a.rmx+b.lmx>ret.mmx)ret.mmx=a.rmx+b.lmx,ret.mxl=a.rmxp,ret.mxr=b.lmxp;
  31. if(b.mmx>ret.mmx)ret.mmx=b.mmx,ret.mxl=b.mxl,ret.mxr=b.mxr;
  32. ret.mmn=a.mmn,ret.mnl=a.mnl,ret.mnr=a.mnr;
  33. if(a.rmn+b.lmn<ret.mmn)ret.mmn=a.rmn+b.lmn,ret.mnl=a.rmnp,ret.mnr=b.lmnp;
  34. if(b.mmn<ret.mmn)ret.mmn=b.mmn,ret.mnl=b.mnl,ret.mnr=b.mnr;
  35. return ret;
  36. }
  37. inline void pushnow(int p){
  38. T[p].tag^=1,T[p].sum*=-1;
  39. T[p].lmx*=-1,T[p].rmx*=-1,T[p].lmn*=-1,T[p].rmn*=-1,T[p].mmx*=-1,T[p].mmn*=-1;
  40. swap(T[p].lmx,T[p].lmn),swap(T[p].rmx,T[p].rmn),swap(T[p].mmx,T[p].mmn);
  41. swap(T[p].lmxp,T[p].lmnp),swap(T[p].rmxp,T[p].rmnp);
  42. swap(T[p].mxl,T[p].mnl),swap(T[p].mxr,T[p].mnr);
  43. }
  44. inline void pushdown(int p){if(T[p].tag)T[p].tag^=1,pushnow(lc),pushnow(rc);}
  45. inline void build(int p,int l,int r){
  46. T[p].l=l,T[p].r=r,T[p].tag=0;
  47. if(l==r){
  48. T[p].sum=T[p].lmx=T[p].lmn=T[p].rmx=T[p].rmn=T[p].mmx=T[p].mmn=a[l];
  49. T[p].lmxp=T[p].rmxp=T[p].lmnp=T[p].rmnp=T[p].mxl=T[p].mxr=T[p].mnl=T[p].mnr=l;
  50. return;
  51. }
  52. build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc],T[p].tag=0;
  53. }
  54. inline void update(int p,int ql,int qr){
  55. if(T[p].l>qr||T[p].r<ql)return;
  56. if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p);
  57. pushdown(p);
  58. if(qr<=mid)update(lc,ql,qr);
  59. else if(ql>mid)update(rc,ql,qr);
  60. else update(lc,ql,mid),update(rc,mid+1,qr);
  61. int tmp=T[p].tag;
  62. T[p]=T[lc]+T[rc],T[p].tag=tmp;
  63. }
  64. int main(){
  65. n=read(),m=read();
  66. for(int i=1;i<=n;++i)a[i]=read();
  67. build(1,1,n);
  68. for(int i=1;i<=m;++i){
  69. if(T[1].mmx<0){printf("%d",ans);return 0;}
  70. ans+=T[1].mmx,update(1,T[1].mxl,T[1].mxr);
  71. }
  72. printf("%d",ans);
  73. return 0;
  74. }

2018.09.30 bzoj2288:生日礼物(贪心+线段树)的更多相关文章

  1. 2018.09.30 bzoj4025: 二分图(线段树分治+并查集)

    传送门 线段树分治好题. 这道题实际上有很多不同的做法: cdq分治. lct. - 而我学习了dzyo的线段树分治+并查集写法. 所谓线段树分治就是先把操作分成lognlognlogn个连续不相交的 ...

  2. 2018.09.12 poj2376Cleaning Shifts(线段树+简单dp)

    传送门 貌似贪心能过啊%%%. 本蒟蒻写的线段树优化dp. 式子很好推啊. f[i]表示覆盖1~i所需的最小代价. 那么显然对于一个区间[li,ri]" role="present ...

  3. L3-2 森森快递 (30 分)(贪心+线段树/分块)

    题目链接:https://pintia.cn/problem-sets/1108203702759940096/problems/1108204121661857798 题目大意: 森森开了一家快递公 ...

  4. BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库

    正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...

  5. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  6. 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)

    2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...

  7. 2018.09.24 bzoj4977: [[Lydsy1708月赛]跳伞求生(贪心+线段树)

    传送门 线段树好题. 这题一看我就想贪心. 先把a,b数组排序. 然后我们选择a数组中最大的b个数(不足b个就选a个数),分别贪心出在b数组中可以获得的最大贡献. 这时可以用线段树优化. 然后交上去只 ...

  8. BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)

    题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...

  9. [九省联考2018]IIIDX 贪心 线段树

    ~~~题面~~~ 题解: 一开始翻网上题解看了好久都没看懂,感觉很多人都讲得不太详细,所以导致一些细节的地方看不懂,所以这里就写详细一点吧,如果有不对的or不懂的可以发评论在下面. 首先有一个比较明显 ...

随机推荐

  1. body 标签

    -图标 &nbsp(空格) -&gt(>) &lt(<) -p标签, 段落 <br \>  做换行 所有的标签分为: 块级标签: div(白板), H系 ...

  2. Eclipse 工程使用相对路径导入Jar包设置

    环境:MyEclipse 6.5 问题:MyEclipse 工程使用相对路径导入Jar包 我们在导入工程时,往往添加Jar都是使用的绝对路径,但这带来了一个问题,不同的用户使用工程都得重新配置Buil ...

  3. Kotlin语言学习笔记(6)

    运算符重载(Operator overloading) 一元运算符 Expression Translated to +a a.unaryPlus() -a a.unaryMinus() !a a.n ...

  4. Lock()与RLock()锁

    资源总是有限的,程序运行如果对同一个对象进行操作,则有可能造成资源的争用,甚至导致死锁 也可能导致读写混乱 锁提供如下方法: 1.Lock.acquire([blocking]) 2.Lock.rel ...

  5. Kconfig详解

    当执行#make menuconfig时会出现内核的配置界面,所有配置工具都是通过读取"arch/$(ARCH)Kconfig"文件来生成配置界面,这个文件就是所有配置的总入口,它 ...

  6. The maximum column size is 767 bytes (Mysql)

     ERROR app.wsutils 419 INCRON: Error: ('HY000', '[HY000] [MySQL][ODBC 5.2(w) Driver][mysqld-5.7.7-rc ...

  7. e.g.-basic-Si

    ! Band structure of silicon. The points listed after plot1d below are the ! vertices joined in the b ...

  8. Linux 查看当前时间

    一.查看和修改Linux的时区1. 查看当前时区命令 : "date -R"2. 修改设置Linux服务器时区方法 A命令 : "tzselect"方法 B 仅 ...

  9. 【校招面试 之 C/C++】第27题 C++ 智能指针(三)之 unique_ptr

    auto_ptr<string> p1(new string ("auto") : //#1 auto_ptr<string> p2; //#2 p2 = ...

  10. 搜索旋转排序数组 II

    跟进“搜索旋转排序数组”,假如有重复元素又将如何? 一句话思路:不能二分,因为复杂度是n eg全是0,找一个1 class Solution { public boolean search(int[] ...