zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Visual C#核心编程之泛型
    Visual C#核心编程之枚举器
    标准的非托管资源的销毁模式
    Visual C#核心编程之LINQ
    Visual C#核心编程之数组和集合
    ACCPSQL第四章上机六
    Visual C#2008核心编程之类型
    一月一代码 3月 kmp 领悟代码
    [转] 技巧 如何统一设置 windows live writer 的 图片大小
    understanding the linux virtual memory management 图序
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12247265.html
Copyright © 2011-2022 走看看