• [BZOJ3638 && BZOJ3272]带修区间不相交最大K子段和(线段树模拟费用流)


    https://www.cnblogs.com/DaD3zZ-Beyonder/p/5634149.html

    k可重区间集问题有两种建图方式,可能这一种才可以被线段树优化。

    换个角度看,这也是一个类似[BZOJ1150]数据备份的可撤销贪心。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define ls (x<<1)
     4 #define rs (ls|1)
     5 #define lson ls,L,mid
     6 #define rson rs,mid+1,R
     7 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     8 using namespace std;
     9 
    10 const int N=100010;
    11 int n,T,x,y,l,r,k,op,ans,top,a[N];
    12 struct Tr{ int lx,rx,mx,sm,pl,pr,p1,p2; };
    13 struct P{ Tr mx,mn; int tag; }v[N<<2];
    14 struct S{ int l,r; }stk[N];
    15 
    16 Tr merge(const Tr &lc,const Tr &rc){
    17     Tr c; c.sm=lc.sm+rc.sm;
    18     c.lx=lc.sm+rc.lx>lc.lx? lc.sm+rc.lx : lc.lx;
    19     c.pl=lc.sm+rc.lx>lc.lx? rc.pl : lc.pl;
    20     c.rx=rc.sm+lc.rx>rc.rx? rc.sm+lc.rx : rc.rx;
    21     c.pr=rc.sm+lc.rx>rc.rx? lc.pr : rc.pr;
    22     c.mx=lc.rx+rc.lx; c.p1=lc.pr; c.p2=rc.pl;
    23     if (c.mx<lc.mx) c.mx=lc.mx,c.p1=lc.p1,c.p2=lc.p2;
    24     if (c.mx<rc.mx) c.mx=rc.mx,c.p1=rc.p1,c.p2=rc.p2;
    25     return c;
    26 }
    27 
    28 void upd(int x){
    29     v[x].mn=merge(v[ls].mn,v[rs].mn);
    30     v[x].mx=merge(v[ls].mx,v[rs].mx);
    31 }
    32 
    33 void push(int x){
    34     if (!v[x].tag) return;
    35     v[x].tag^=1;
    36     swap(v[ls].mx,v[ls].mn); v[ls].tag^=1;
    37     swap(v[rs].mx,v[rs].mn); v[rs].tag^=1;
    38 }
    39 
    40 void put(int x,int p,int k){
    41     v[x].mx=(Tr){k,k,k,k,p,p,p,p};
    42     v[x].mn=(Tr){-k,-k,-k,-k,p,p,p,p};
    43 }
    44 
    45 void build(int x,int L,int R){
    46     if (L==R){ put(x,L,a[L]); return; }
    47     int mid=(L+R)>>1;
    48     build(lson); build(rson); upd(x);
    49 }
    50 
    51 void mdf(int x,int L,int R,int pos,int k){
    52     if (L==R){ put(x,pos,k); return; }
    53     int mid=(L+R)>>1; push(x);
    54     if (pos<=mid) mdf(lson,pos,k); else mdf(rson,pos,k);
    55     upd(x);
    56 }
    57 
    58 Tr que(int x,int L,int R,int l,int r){
    59     if (L==l && r==R) return v[x].mx;
    60     int mid=(L+R)>>1; push(x);
    61     if (r<=mid) return que(lson,l,r);
    62     else if (l>mid) return que(rson,l,r);
    63         else return merge(que(lson,l,mid),que(rson,mid+1,r));
    64 }
    65 
    66 void rev(int x,int L,int R,int l,int r){
    67     if (L==l && r==R){ swap(v[x].mn,v[x].mx); v[x].tag^=1; return; }
    68     int mid=(L+R)>>1; push(x);
    69     if (r<=mid) rev(lson,l,r);
    70     else if (l>mid) rev(rson,l,r);
    71         else rev(lson,l,mid),rev(rson,mid+1,r);
    72     upd(x);
    73 }
    74 
    75 void solve(int l,int r,int k){
    76     ans=0; top=0;
    77     while (k--){
    78         Tr tmp=que(1,1,n,l,r);
    79         if (tmp.mx>0) ans+=tmp.mx; else break;
    80         rev(1,1,n,tmp.p1,tmp.p2);
    81         stk[++top]=(S){tmp.p1,tmp.p2};
    82     }
    83     for (int i=top; i; i--) rev(1,1,n,stk[i].l,stk[i].r);
    84     printf("%d
    ",ans);
    85 }
    86 
    87 int main(){
    88     freopen("bzoj3272.in","r",stdin);
    89     freopen("bzoj3272.out","w",stdout);
    90     scanf("%d",&n);
    91     rep(i,1,n) scanf("%d",&a[i]);
    92     build(1,1,n);
    93     for (scanf("%d",&T); T--; ){
    94         scanf("%d",&op);
    95         if (op==0) scanf("%d%d",&x,&y),mdf(1,1,n,x,y);
    96             else scanf("%d%d%d",&l,&r,&k),solve(l,r,k);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    net core 2 读取appsettings.json
    转: C# 根据当前时间获取,本周,本月,本季度等时间段 .Net中Exception
    转:5种回到顶部的写法从实现到增强
    转:jQuery 常见操作实现方式
    NLog 自定义字段 写入 oracle
    转:C# 使用NLog记录日志
    转:NLog之:文件类型目标(File target)
    springboot2.x+jwt+shiro最简单、最快速整合方式
    windows部署mindoc
    docker安装mongodb
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10360839.html
Copyright © 2020-2023  润新知