Luo Gu P3084 [USACO13OPEN] Photos

topic

\(DP\)

Reset state \ (dp [i] \) of \ (I \) position of the spot put cattle, before \ (I \) position to get up cattle.

There equation \ (DP [I] = max (DP [J] +. 1, DP [I]) \) , but we do not know what \ (J \) can \ (I \) is not within range

Since \ (i \) position to put the cattle, and because \ (i \) zone where only put a, \ (J \) can not be with \ (i \) belong to the same interval, and because each section has one and have a cow spots, so each section must have a number for each \ (i \) , there will be some interval in the subscript \ (j \) can be used to transfer \ (i \) , now to find how each is transformed to \ (I \) corresponding to \ (J \) section where the problem is.

Each section there will be two spots cattle conditions: First \ (j \) must be better than \ (i \) interval left point where all of the position after the leftmost this is less evident, this left set point \ (L \) of \ (I \) corresponding to \ (J \) maximum number.

Each section has at least one spot cattle this condition: as has been enumerated to the first \ (I \) positions, and therefore \ (R & lt \) than \ (I \) small interval must have a value, \ (J \ ) must be in a \ (r \) than \ (i \) small and \ (l \) the biggest \ (l \) to the right, because we are dynamic programming, so we only need to use \ (dp [j] \) in this state, and this state in the count before \ (dp [j] \) when he has met the requirements of the subject, and it \ (j \) must belong \ (i \) before \ (l \) maximum interval

#include <bits/stdc++.h>
#define N 2010010
using namespace std;
deque <int> q;
int n, m, ans, dp[N], l[N], r[N];//dp[i]表示i位置放斑点牛,前i个位置所得到的最多的牛。
//r[i]代表着i之后的区间的最小左端点。j一定不能比r[i]大 
//l[i]代表着i之前的区间的最大左端点。j同时不能比l[i]小,因为如果j比l[i]小的话,那 
inline void init()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n + 1; i++)
        r[i] = i;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        r[b] = min(a, r[b]);//b位置的j取值一定要比r小
        l[b + 1] = max(a, l[b + 1]);//b+1的j位置一定要比l大
    }
    for (int i = n; i >= 1; i--)//此i的r值必须要比i+1小,因为i+1取不到的,i也不能取到。 
        r[i] = min(r[i + 1], r[i]);
    for (int i = 2; i <= n + 1; i++)//此i的l值必须必i-1大,因为首先需要满足i-1位置的值。 
        l[i] = max(l[i - 1], l[i]);
}
int main()
{
    init();
    q.push_back(0);
    int j = 1;
    for (int i = 1; i <= n + 1; i++)
    {
        while (j < r[i])//j首先要比r小, 
        {
            if (dp[j] != -1)
            {
                while (!q.empty() && dp[j] > dp[q.back()]) 
                    q.pop_back();
                q.push_back(j);
            }
            j++;
        }
        while (!q.empty() && q.front() < l[i])//其次要比l大 
            q.pop_front();
        if (!q.empty()) dp[i] = max(dp[i], dp[q.front()] + (int) (i != n + 1) );
        else dp[i] = -1;
    }
    printf("%d", dp[n + 1] ? dp[n + 1] : -1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/liuwenyao/p/11824138.html