CF833B The Bakery(线段树维护dp)

对于暴力dp来说,对于当前i位置分成j段的答案就是f[l][j-1]+val(l+1,i),对于所有符合条件的答案取一个max

我们发现暴力会t,并且是取max,想到用线段树维护前一次的dp,这样只要dpk次就能获得答案。

至于val,其实就是区间修改,对于每个点,他有贡献的区间就是离他相同最近的点到他本身的距离,因此用线段树优化dp

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int n,k;
int a[N];
int last[N];
int pre[N];
struct node{
    int l,r;
    int mx;
    int lazy;
}tr[N<<2];
int f[N];
void pushup(int u){
    tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,0,0};
    }
    else{
        tr[u]={l,r,0,0};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void rebuild(int u,int l,int r){
    tr[u].lazy=0;
    if(l==r){
        tr[u].mx=f[l];
    }
    else{
        int mid=l+r>>1;
        rebuild(u<<1,l,mid);
        rebuild(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void pushdown(int u){
    int x=tr[u].lazy;
    tr[u<<1].mx+=x;
    tr[u<<1|1].mx+=x;
    tr[u<<1].lazy+=x;
    tr[u<<1|1].lazy+=x;
    tr[u].lazy=0;
}
void modify(int u,int l,int r,int x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].mx+=1;
        tr[u].lazy+=1;
        return ;
    }
    if(tr[u].lazy){
        pushdown(u);
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,x);
    if(r>mid)
        modify(u<<1|1,l,r,x);
    pushup(u);
}
int query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        return tr[u].mx;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    int ans=0;
    if(l<=mid){
        ans=query(u<<1,l,r);
    }
    if(r>mid)
        ans=max(ans,query(u<<1|1,l,r));
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    int i;
    for(i=1;i<=n;i++){
        cin>>a[i];
        pre[i]=last[a[i]];
        last[a[i]]=i;
    }
    build(1,0,n);
    for(i=1;i<=k;i++){
        rebuild(1,0,n);
        for(int j=i;j<=n;j++){
            modify(1,pre[j],j-1,1);
            f[j]=query(1,0,j-1);
        }
    }
    cout<<f[n]<<endl;
}
View Code

 

posted @ 2020-10-20 22:28  朝暮不思  阅读(102)  评论(0编辑  收藏  举报