dtoi4649 光明
Posted 1124828077ccj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dtoi4649 光明相关的知识,希望对你有一定的参考价值。
题意:
现在有 n 块水晶石板形成一个序列,每块水晶石板有一个权值 。
第 i 块水晶石板的大小是 ai?∗bi?的,也就是有 ai?∗bi? 个格子。
A和B要拿这些石板玩游戏。
每次玩游戏,A都会先选择一个区间 [l,r],B只能选择这个区间的一个子区间。
对于这个子区间中的每个石板,A可以任意指定一个点作为起点,B需要从这个起点出发不重不漏地经过每一个格子并回到这个点(每次移动只能向上下左右中的一个方向),那么B可以获得这块石板的权值,否则A获得这块石板的权值。B每次都想最大化自己的得分减去A的得分。注意,B不可以选择一个空集。
现在有 q 次操作,每次操作是三种之一
1 x a b:修改第 x 块水晶石板的大小为 a*b
2 x w:修改第 x 块水晶石板的权值为 w
3 l r:A和B玩游戏,A选择了区间 [l,r],B需要选择一个 [l,r] 中的子区间,最大化(B的得分-A的得分)
为了避免石板的长或宽为 1 时回到起始点存在问题,始终保证 ai?>1,bi?>1 。
题解:
首先我们要知道,某一块水晶石板什么时候贡献为w,什么时候贡献为-w。
只要长或者宽有一个为偶数即可完成这个任务,贡献就为w,否则为-w。如果有一个是偶数,那么我们可以蛇形走位然后再绕回来。(自己画一画就知道了)
接下来就是动态维护区间最大连续子段和,可以采用线段树维护。这是一个经典问题,我们需要维护左最大,右最大和总的最大值就可以了。
#include<cstdio> #include<algorithm> #include<cstdlib> using namespace std; const int INF=1e9; int n,w[100002],a[100002],b[100002]; typedef struct{ int lMax,rMax,Max,sum; }P; P p[400002],ans1,ans2; void hb(int root){ p[root].sum=p[root*2].sum+p[root*2+1].sum; p[root].Max=max(max(p[root*2].Max,p[root*2+1].Max),p[root*2].rMax+p[root*2+1].lMax); p[root].lMax=max(p[root*2].lMax,p[root*2].sum+p[root*2+1].lMax); p[root].rMax=max(p[root*2+1].rMax,p[root*2+1].sum+p[root*2].rMax); } void hb2(int root){ ans2.sum=ans1.sum+p[root].sum; ans2.Max=max(max(ans1.Max,p[root].Max),ans1.rMax+p[root].lMax); ans2.lMax=max(ans1.lMax,ans1.sum+p[root].lMax); ans2.rMax=max(p[root].rMax,p[root].sum+ans1.rMax); } void build(int root,int begin,int end){ if (begin==end) { if (a[begin]%2==0 || b[begin]%2==0)p[root].Max=p[root].lMax=p[root].rMax=p[root].sum=w[begin]; else p[root].Max=p[root].lMax=p[root].rMax=p[root].sum=-w[begin]; return; } int mid=(begin+end)/2; build(root*2,begin,mid);build(root*2+1,mid+1,end); hb(root); } void gengxin(int root,int begin,int end,int wz,int z){ if (begin>wz || end<wz)return; if (begin==end) { p[root].Max=p[root].lMax=p[root].rMax=p[root].sum=z; return; } int mid=(begin+end)/2; gengxin(root*2,begin,mid,wz,z);gengxin(root*2+1,mid+1,end,wz,z); hb(root); } void chaxun(int root,int begin,int end,int begin2,int end2){ if (begin>end2 || end<begin2)return; if (begin>=begin2 && end<=end2) { ans1=ans2;hb2(root);return; } int mid=(begin+end)/2; chaxun(root*2,begin,mid,begin2,end2);chaxun(root*2+1,mid+1,end,begin2,end2); } int main() { scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d",&w[i]); for (int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]); build(1,1,n); int q;scanf("%d",&q); while(q--) { int op; scanf("%d",&op); if (op==1) { int x,aa,bb; scanf("%d%d%d",&x,&aa,&bb); a[x]=aa;b[x]=bb; if (a[x]%2 && b[x]%2)gengxin(1,1,n,x,-w[x]);else gengxin(1,1,n,x,w[x]); } if (op==2) { int x,ww; scanf("%d%d",&x,&ww); w[x]=ww; if (a[x]%2 && b[x]%2)gengxin(1,1,n,x,-w[x]);else gengxin(1,1,n,x,w[x]); } if (op==3) { int l,r; scanf("%d%d",&l,&r); ans2.sum=0;ans2.lMax=ans2.rMax=ans2.Max=-INF; chaxun(1,1,n,l,r); printf("%d ",ans2.Max); } } return 0; }
以上是关于dtoi4649 光明的主要内容,如果未能解决你的问题,请参考以下文章