[USACO13DEC] Optimal Milking

Description

n个点排成一排,点有点权,要求支持两种操作:

  1. 修改某个点的点权
  2. 询问取出任意多且不相邻的点的点权和最大值

Solution

跟最大子段和一样,可以用分治做,用线段树记录一下左右端点选没选就行了。

然而并想不到

Code

#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 40005
typedef long long ll;
using std::min;
using std::max;
using std::swap;
#define ls cur<<1
#define rs cur<<1|1

int n,m,val[N];
int mx[N<<2][4];//0 not not  1 not yes   2 yes not   3 yes yes
//0->0+2 1+0 0+0
//1->0+3 0+1 1+1
//2->3+0 2+0 2+2
//3->2+1 3+1 2+3

void pushup(int cur){
    mx[cur][0]=max(mx[ls][0]+mx[rs][2],max(mx[ls][1]+mx[rs][0],mx[ls][0]+mx[rs][0]));
    mx[cur][1]=max(mx[ls][0]+mx[rs][3],max(mx[ls][0]+mx[rs][1],mx[ls][1]+mx[rs][1]));
    mx[cur][2]=max(mx[ls][3]+mx[rs][0],max(mx[ls][2]+mx[rs][0],mx[ls][2]+mx[rs][2]));
    mx[cur][3]=max(mx[ls][2]+mx[rs][1],max(mx[ls][3]+mx[rs][1],mx[ls][2]+mx[rs][3]));
}

inline int getint(){
    int X=0;int w=0;char ch=0;
    while(!isdigit(ch))w|=ch=='-',ch=getchar();
    while( isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}

void build(int cur,int l,int r){
    if(l==r){
        mx[cur][0]=mx[cur][1]=mx[cur][2]=0;
        mx[cur][3]=val[l];
        return;
    }
    int mid=l+r>>1;
    build(cur<<1,l,mid);build(cur<<1|1,mid+1,r);
    pushup(cur);
}

void modify(int cur,int l,int r,int ql,int c){
    if(l==r){
        mx[cur][3]=c;
        return;
    }
    int mid=l+r>>1;
    if(ql<=mid) modify(cur<<1,l,mid,ql,c);
    else modify(cur<<1|1,mid+1,r,ql,c);
    pushup(cur);
}

signed main(){
    // freopen("in.txt","r",stdin);
    n=getint();m=getint();
    for(int i=1;i<=n;i++)
        val[i]=getint();
    build(1,1,n);
    ll ans=0;
    while(m--){
        int x=getint(),y=getint();
        modify(1,1,n,x,y);
        ans+=(ll)max(mx[1][0],max(mx[1][2],max(mx[1][3],mx[1][1])));
    } printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/YoungNeal/p/9571037.html