zoukankan      html  css  js  c++  java
  • 【BZOJ5324】守卫(JXOI2018)-区间DP+优化

    测试地址:守卫
    做法:本题需要用到区间DP+优化。
    看到数据范围,容易想到令f(l,r)为区间[l,r]的答案,我们来考虑怎么转移。
    对于一个区间[l,r],首先点r是一定要有人的,对于点r,它能看到的所有点可以这样求:从点r1开始,如果它到点r的斜率和上一个能看到的点到点r的斜率相比更小,那么当前点就能看到,否则就看不到(可以把坐标系转换为以点r为极点的极坐标系来考虑),这样从右往左扫一遍就可以求出它能看到的所有点了。于是我们可以O(n2)预处理出这些信息。
    那我们有了这些信息,再考虑每一个点r看不到的点的连续区间[lk,rk],注意到对于x>rk+1,点x都是不可能看到区间[lk,rk]中的点的,这个结论画画图也可以得出来。由这个结论我们可以得出,每个这样的区间的决策对整个区间[l,r]来说,贡献是独立的,而对于一个区间[lk,rk],要使得里面的点全部被看到,可以选择在点rk或点rk+1布置一个人,贡献分别为f(lk,rk)f(lk,rk+1),因此我们有状态转移方程:
    f(l,r)=1+min(f(lk,rk),f(lk,rk+1))
    这个方程是O(n3)的,显然不能通过此题,这就需要我们的优化。从方程本身的角度已经很难优化下去了,因此我们对求方程的方法进行优化。
    注意到rk+1<r,因此我们从小到大枚举r来确保当前状态所需要的状态都已经被计算,而在r固定的情况下,l左移时,经过的r看不到的连续区间的贡献就可以顺便记录下来,这样我们就可以做到O(n2)的总时间复杂度了,于是我们就完成了这一题。
    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    ll n,h[5010],f[5010][5010];
    bool see[5010][5010];
    
    int main()
    {
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
            scanf("%lld",&h[i]);
    
        for(ll i=1;i<=n;i++)
        {
            see[i][i]=0;
            for(ll j=i-1,last=0;j>=1;j--)
            {
                if (!last||(h[i]-h[j])*(i-last)<(h[i]-h[last])*(i-j))
                {
                    see[i][j]=1;
                    last=j;
                }
                else see[i][j]=0;
            }
        }
    
        ll ans=0;
        for(ll r=1;r<=n;r++)
        {
            ll lastans=1,lastr=0;
            for(ll l=r;l>=1;l--)
            {
                if (see[r][l])
                {
                    if (lastr)
                    {
                        lastans+=min(f[l+1][lastr],f[l+1][lastr+1]);
                        lastr=0;
                    }
                }
                else
                {
                    if (!lastr) lastr=l;
                    f[l][r]+=min(f[l][lastr],f[l][lastr+1]);
                }
                f[l][r]+=lastans;
                ans^=f[l][r];
            }
        }
        printf("%lld",ans);
    
        return 0;
    }
  • 相关阅读:
    关键字--super
    JSP学习笔记3--指令元素
    JSP学习笔记2--JSP基本元素
    力扣233.数字1出现的次数
    JSP学习笔记1
    继承
    Cocos2dx-Lua中Sprite精灵的3种创建方法
    cocos2dx Action动作 (3)CCSkewTo、CCSkewBy
    cocos2dx Action动作解析(2)
    cocos2dx Action动作解析(1)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793355.html
Copyright © 2011-2022 走看看