题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4094
题目大意:
约翰有N 台挤奶机器,这些机器排成了一条直线,其中第i台机器工作效率是Ai,也就是说工作一天可以产出Ai。约翰将会开动这些机器工作Q 天。每天一早,约翰一定会维修一台机器。在第i 天早上,他维修的是第Ti 台机器,经过维修之后,这台机器的工作效率将会变成Di。在任何时候,位置相邻的两台机器都不能同时工作。请问约翰每天应该选择开动哪些机器,才能让这Q 天的总产出之和最大?
题解:
线段树
脖子上没有东西的我天真的以为直接每天取奇数位的或者偶数位的机器开,维护两个变量:和&开奇数位机器的和。但是直到我只过了两个点才发现明显的错啊qwq反例还是容易找到的[尽管我找到的反例其实并不是反例= =不管反正知道错了。
所以我的线段树后来就维护了四个变量,左端点取右端点不取,左端点不取右端点取,两个端点都取/不取的最大值。
方便不打错就直接开了个二维小数组~
方便记答案还多开了个变量mx,就是上面那四个东西中的最大值。。
好像知道怎么去维护就应该会做了吧嗯。
想了还不会再看看我那长得丑的代码↓
([0][0]就表示左右端点都不取..依此类推)
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; #define maxn 201000 struct tree { int l,r,lc,rc;LL a[2][2],mx; }tr[maxn];int tlen; LL mymax(LL x,LL y){return (x>y)?x:y;} void bt(int l,int r) { tlen++;int now=tlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=-1; memset(tr[now].a,0,sizeof(tr[now].a)); tr[now].mx=0; if (l<r) { int mid=(l+r)>>1; tr[now].lc=tlen+1;bt(l,mid); tr[now].rc=tlen+1;bt(mid+1,r); } } void updata(int now,int lc,int rc)//四种情况分别更新 { tr[now].a[0][0]=mymax(tr[lc].a[0][1]+tr[rc].a[0][0],tr[lc].a[0][0]+tr[rc].a[1][0]); tr[now].a[1][0]=mymax(tr[lc].a[1][1]+tr[rc].a[0][0],tr[lc].a[1][0]+tr[rc].a[1][0]); tr[now].a[0][1]=mymax(tr[lc].a[0][1]+tr[rc].a[0][1],tr[lc].a[0][0]+tr[rc].a[1][1]); tr[now].a[1][1]=mymax(tr[lc].a[1][1]+tr[rc].a[0][1],tr[lc].a[1][0]+tr[rc].a[1][1]); } void change(int now,int x,LL k) { if (tr[now].l==tr[now].r) { tr[now].a[1][1]=k; tr[now].mx=k; return; } int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc; if (x<=mid) change(lc,x,k); else change(rc,x,k); updata(now,lc,rc); tr[now].mx=mymax(tr[now].a[0][0],tr[now].a[0][1]); tr[now].mx=mymax(tr[now].mx,mymax(tr[now].a[1][0],tr[now].a[1][1])); } int main() { //freopen("optmilk.in","r",stdin); //freopen("optmilk.out","w",stdout); int n,q,i;LL ans,x,c; scanf("%d%d",&n,&q); tlen=0;bt(1,n); for (i=1;i<=n;i++) { scanf("%lld",&x); change(1,i,x); }ans=0; while (q--) { scanf("%lld%lld",&x,&c); change(1,x,c); ans+=tr[1].mx; }printf("%lld ",ans); return 0; }