zoukankan      html  css  js  c++  java
  • 神建模+dp——cf1236E

    首先将两个人的所有可能的操作建立成一个模型:m+2行n列的矩阵

    序列A对应图上的格子(i,Ai),第0行作为起点,最后一行作为终点,每个点可以向左下,下,右下走,每种可行的情况对应图上的一条路径

    推出一个性质:对于第一行每个起点,其能到达的终点范围必定是一个连续的区间

    那么我们只要求出每个起点能到达的范围[l,r],设第i个起点在向左下移动时被挡住L[i]步,那么其最后的位置是i+m+1-L[i]

    考虑只向左走的情况,对于每个起点,当然是能向左走就向左走。除非在某一步被障碍物挡住了

    考虑到上面的障碍作用更大(上面的障碍可能导致下面的障碍失效)所以自下往上考虑每个障碍物的影响

      第i行的障碍物只会影响起点(0,A[i]+i),这个点被挡住了一步,那么L[i]可以先从L[i+1]继承状态,再+1,

      因为第i个起点向左下被挡住,向下走到的那个点,等价于第i+1个点不被挡住时走到该行的状态,因为比第i+1个点多被挡住了一次,所以需要+1

    #include <bits/stdc++.h>
    using namespace std;
    const int N=3e5+100;
    const int T=1e5;
    #define ll long long
    int n,m,a[N],L[N],R[N];
    
    int main()
    {
        cin>>n>>m;
        if(n==1)return printf("0"),0;
        for(int i=1;i<=m;i++)scanf("%d",&a[i]);
        for(int i=m;i>=1;i--)
        {
            L[i+a[i]+T]=L[i+a[i]+1+T]+1;
            R[a[i]-i+T]=R[a[i]-i-1+T]+1;
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            int l=max(1,i-(m+1)+L[i+T]);
            int r=min(n,i+(m+1)-R[i+T]);
            ans+=1ll*(r-l+1);
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    xcode Git
    The OAuth 2.0 Authorization Framework
    Apache Commons 工具集介绍
    遍历map
    ClassLoader 提供了两个方法用于从装载的类路径中取得资源:
    转:mysql 索引
    StringBuilder与StringBuffer
    第四次作业
    Java Class 与 Object
    软件测试中条件覆盖,路径覆盖,语句覆盖,分支覆盖的区别
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11733493.html
Copyright © 2011-2022 走看看