首页 > 其他分享 >#线段树,模拟费用流#CF280D k-Maximum Subsequence Sum

#线段树,模拟费用流#CF280D k-Maximum Subsequence Sum

时间:2024-04-05 21:33:22浏览次数:22  
标签:rmin int Sum Maximum Subsequence wmax wmin lmin sum

题目

给定一个大小为 \(n\) 的序列,要求支持单点修改和查询区间内至多 \(k\) 个不交子区间之和的最大值(可以不取)


分析

考虑源点向每个点、每个点向汇点流流量1费用0的边,每个点向右边的点流流量1费用\(a_i\)的边,流量最大为 \(k\),这样构建出一个费用流的模型。

很显然,退流相当于给区间取反,而可以利用反悔贪心,在线段树上维护最大子段和和最小子段和,在最大子段和大于0的情况下取反至多 \(k\) 次区间,查询完再恢复原状

复杂度 \(O(nk\log n)\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <stack>
using namespace std;
const int N=100011; int n,a[N];
stack<pair<int,int> >st;
int iut(){
    int ans=0,f=1; char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans*f;
}
void print(int ans){
    if (ans<0) putchar('-'),ans=-ans;
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
struct Rec{int l,r,z;};
struct rec{
    Rec wmax,wmin,lmax,lmin,rmax,rmin; int sum,lazy;
    void ptag(int x,int y){
        wmax=wmin=lmax=lmin=rmax=rmin=(Rec){x,x,y};
        sum=y,lazy=0;
    }
    void rev(){
        swap(wmax,wmin),swap(lmax,lmin),swap(rmax,rmin);
        wmax.z=-wmax.z,wmin.z=-wmin.z,
        lmax.z=-lmax.z,lmin.z=-lmin.z,
        rmax.z=-rmax.z,rmin.z=-rmin.z;
        sum=-sum,lazy^=1;
    }
}w[N<<2];
rec pup(rec f,rec g){
    rec h; h.lazy=0;
    h.sum=f.sum+g.sum;
    if (f.lmax.z<f.sum+g.lmax.z) h.lmax=(Rec){f.lmax.l,g.lmax.r,f.sum+g.lmax.z};
        else h.lmax=f.lmax;
    if (f.lmin.z>f.sum+g.lmin.z) h.lmin=(Rec){f.lmin.l,g.lmin.r,f.sum+g.lmin.z};
        else h.lmin=f.lmin;
    if (g.rmax.z<f.rmax.z+g.sum) h.rmax=(Rec){f.rmax.l,g.rmax.r,f.rmax.z+g.sum};
        else h.rmax=g.rmax;
    if (g.rmin.z>f.rmin.z+g.sum) h.rmin=(Rec){f.rmin.l,g.rmin.r,f.rmin.z+g.sum};
        else h.rmin=g.rmin;
    h.wmax=f.wmax.z>g.wmax.z?f.wmax:g.wmax;
    if (h.wmax.z<f.rmax.z+g.lmax.z) h.wmax=(Rec){f.rmax.l,g.lmax.r,f.rmax.z+g.lmax.z};
    h.wmin=f.wmin.z<g.wmin.z?f.wmin:g.wmin;
    if (h.wmin.z>f.rmin.z+g.lmin.z) h.wmin=(Rec){f.rmin.l,g.lmin.r,f.rmin.z+g.lmin.z};
    return h;
}
void build(int k,int l,int r){
    if (l==r){
        w[k].ptag(l,a[l]);
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    w[k]=pup(w[k<<1],w[k<<1|1]);
}
void update(int k,int l,int r,int x,int y){
    if (l==r){
        w[k].ptag(x,y);
        return;
    }
    int mid=(l+r)>>1;
    if (w[k].lazy){
        w[k<<1].rev(),w[k<<1|1].rev();
        w[k].lazy=0;
    }
    if (x<=mid) update(k<<1,l,mid,x,y);
        else update(k<<1|1,mid+1,r,x,y);
    w[k]=pup(w[k<<1],w[k<<1|1]);
}
void flip(int k,int l,int r,int x,int y){
    if (l==x&&r==y){
        w[k].rev();
        return;
    }
    int mid=(l+r)>>1;
    if (w[k].lazy){
        w[k<<1].rev(),w[k<<1|1].rev();
        w[k].lazy=0;
    }
    if (y<=mid) flip(k<<1,l,mid,x,y);
    else if (x>mid) flip(k<<1|1,mid+1,r,x,y);
        else flip(k<<1,l,mid,x,mid),flip(k<<1|1,mid+1,r,mid+1,y);
    w[k]=pup(w[k<<1],w[k<<1|1]);
}
rec query(int k,int l,int r,int x,int y){
    if (l==x&&r==y) return w[k];
    int mid=(l+r)>>1;
    if (w[k].lazy){
        w[k<<1].rev(),w[k<<1|1].rev();
        w[k].lazy=0;
    }
    if (y<=mid) return query(k<<1,l,mid,x,y);
    else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
        else return pup(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
int main(){
    n=iut();
    for (int i=1;i<=n;++i) a[i]=iut();
    build(1,1,n);
    for (int Q=iut();Q;--Q)
    if (iut()){
        int l=iut(),r=iut(),k=iut(),ans=0;
        while (k--){
            rec t=query(1,1,n,l,r);
            if (t.wmax.z<=0) break;
            ans+=t.wmax.z;
            flip(1,1,n,t.wmax.l,t.wmax.r);
            st.push(make_pair(t.wmax.l,t.wmax.r));
        }
        print(ans),putchar(10);
        while (!st.empty()) flip(1,1,n,st.top().first,st.top().second),st.pop();
    }else{
        int x=iut(),y=iut();
        update(1,1,n,x,y);
    }
    return 0;
}

标签:rmin,int,Sum,Maximum,Subsequence,wmax,wmin,lmin,sum
From: https://www.cnblogs.com/Spare-No-Effort/p/18116242

相关文章

  • LeetCode in Python 300. Longest Increasing Subsequence (最长递增子序列)
    求最长递增子序列是深度优先搜索(DFS)的一种应用,有两种比较好的方法可以解决。第一种是动态规划法,时间复杂度为O(n*n),即设置边界条件和更新迭代公式求解最优解。第二种使用二分查找将时间复杂度降为O(nlogn)。本文给出两种方法的实现代码及说明。示例:图1最长递增子序列输入......
  • CF1924D Balanced Subsequences 题解
    先判掉\(k>\min(n,m)\)的情况。首先有个明显的计算最长合法括号子序列的贪心方法:初始一个值为\(0\)的计数器,从左到右枚举每个字符,遇到(时将计数器加一,遇到)时如果计数器不为\(0\)就减一然后将答案加一。考虑绘制它的折线图。初始时纵坐标为\(0\),从左到右枚举每个字符......
  • Least Prefix Sum
    题目链接Hello2023C.LeastPrefixSum思路:仔细看式子,发现可以对它进行推理(mmm是定值,1≤......
  • ceisum 画矩形 画带高度的矩形 画竖起来的矩形
    一、画矩形,每个点不带高度,距离地表500米viewer.entities.add({polygon:{hierarchy:newCesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray([......
  • LeetCode 2461. Maximum Sum of Distinct Subarrays With Length K
    原题链接在这里:https://leetcode.com/problems/maximum-sum-of-distinct-subarrays-with-length-k/description/题目:Youaregivenanintegerarray nums andaninteger k.Findthemaximumsubarraysumofallthesubarraysof nums thatmeetthefollowingconditi......
  • 生信小白菜之关于summarize函数的一切(part 1)
    准备包和示例数据library(dplyr)library(nycflights13)library(ggplot2)summarize()的基本用法#获取摘要的函数#作用是将数据框折叠成一行#举例summarise(flights,delay=mean(dep_delay,na.rm=T))#第二个参数新的一列,也是根据数据框原有数据计算得来#返回结......
  • 从零开始 使用OMNET++结合VEINS,INET和SUMO的联合仿真
    背景知识当我们探索未来的交通系统和智能交通解决方案时,车辆到一切(Vehicle-to-Everything,V2X)通信技术显得尤为重要。V2X是指在车辆与车辆(V2V)、车辆与基础设施(V2I)、车辆与行人(V2P)以及车辆与网络(V2N)之间进行的通信。这种技术能够提高道路安全,优化交通流量,减少拥堵,提升驾驶体验......
  • SUM-ACM,3月24-3-31周报
    两场天梯赛和一场atcoder。主要错误知识点在于字符串的处理和并查集的掌握不够,不懂灵活运用。第一场pta天梯赛7-56翻了一道字符串的题,我只拿了14分。我不熟悉一个点,f(i,0,s.length())是有问题的,在replace后,s.length()会改变,这个时候replace不是一个好的选择。我们只需要输......
  • arco-design 组件库中用 table 组件,做金额合计 sum
    <a-table:columns="columns":data="data":scroll="scroll":summary="summary"><template#summary-cell="{column,record,rowIndex}"><div:style="getColorStyle(column,record)&......
  • SQL95 从 Products 表中检索所有的产品名称以及对应的销售总数(sum() ,group by..)
    selectprod_name,sum(quantity)asquant_soldfromProductsPinnerjoinOrderItemsOIonP.prod_id=OI.prod_idgroupbyprod_name;......