P3084 [USACO13OPEN]照片Photo (dp+单调队列优化)

题目链接:传送门

题目:

题目描述

Farmer John has decided to assemble a panoramic photo of a lineup of his N cows (1 <= N <= 200,000), which, as always, are conveniently numbered from 1..N. Accordingly, he snapped M (1 <= M <= 100,000) photos, each covering a contiguous range of cows: photo i contains cows a_i through b_i inclusive. The photos collectively may not necessarily cover every single cow.

After taking his photos, FJ notices a very interesting phenomenon: each photo he took contains exactly one cow with spots! FJ was aware that he had some number of spotted cows in his herd, but he had never actually counted them. Based on his photos, please determine the maximum possible number of spotted cows that could exist in his herd. Output -1 if there is no possible assignment of spots to cows consistent with FJ‘s photographic results.

输入输出格式
输入格式:

* Line 1: Two integers N and M.

* Lines 2..M+1: Line i+1 contains a_i and b_i.

输出格式:

* Line 1: The maximum possible number of spotted cows on FJ‘s farm, or -1 if there is no possible solution.

输入输出样例
输入样例#1:

5 3
1 4
2 5
3 4 

输出样例#1:

1 

说明

There are 5 cows and 3 photos. The first photo contains cows 1 through 4, etc.

From the last photo, we know that either cow 3 or cow 4 must be spotted. By choosing either of these, we satisfy the first two photos as well.

思路:

  如果要把牛放在第i个位置,它之前的那只牛应该放在[li, ri]之间,根据输入处理出li和ri,就可以转移状态了。

  读入x,y时,用x更新ly+1,用x-1更新ry。

  读入结束之后从前往后扫一遍,用li-1更新li;再从后往前扫一遍,用ri+1更新ri。

  然后就可以跑dp了,f[i] = max{f[j] | li ≤ j ≤ ri}

状态:

  f[i] 表示把最后一只牛放在第i个位置的最大数量。

状态转移方程:

  f[i] = max{f[j] | li ≤ j ≤ ri}

#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 2e5 + 5;
#define tomax(a, b) a = a>b?a:b
#define tomin(a, b) a = a<b?a:b

int N, M, l[MAX_N], r[MAX_N];
int f[MAX_N];

int main()
{
//    freopen("testdata.in", "r", stdin);
    cin >> N >> M;
    for (int i = 1; i <= N+1; i++)
        r[i] = i-1;
    for (int i = 1; i <= M; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        tomin(r[y], x-1);
        tomax(l[y+1], x);
    }
    for (int i = 2; i <= N+1; i++)
        tomax(l[i], l[i-1]);
    for (int i = N; i >= 1; i--)
        tomin(r[i], r[i+1]);
    memset(f, -1, sizeof f);
    f[0] = 0;
    for (int i = 1; i <= N+1; i++)
        for (int j = l[i]; j <= r[i]; j++) if(f[j] != -1)
            tomax(f[i], f[j] + (i!=N+1 ? 1 : 0));

    cout << f[N+1] << endl;
    return 0;
}
/*
5 3
1 4
2 4
1 1
*/

本来是瞄了一眼题解,理解了思路之后准备不优化暴力T一发的,结果直接AC了,还跑得贼快?-。=

不过这样子写应该可以被两只牛的大数据卡掉:

200000 2
1 100000
100001 200000

献上单调队列优化的正解:

#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 2e5 + 5;
#define tomax(a, b) a = a>b?a:b
#define tomin(a, b) a = a<b?a:b

int N, M, l[MAX_N], r[MAX_N];
int h, t, q[MAX_N], f[MAX_N];

int main()
{
    cin >> N >> M;
    memset(f, 0, sizeof f);
    for (int i = 1; i <= N+1; i++)
        r[i] = i-1;
    for (int i = 1; i <= M; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        tomin(r[y], x-1);
        tomax(l[y+1], x);
    }
    for (int i = 2; i <= N+1; i++)
        tomax(l[i], l[i-1]);
    for (int i = N; i >= 1; i--)
        tomin(r[i], r[i+1]);
    int j = 1;
    h = 1, t = 0, q[++t] = 0;
    for (int i = 1; i <= N+1; i++) {
        while (j <= N && j <= r[i]) {
            if (f[j] == -1) {
                ++j;
                continue;
            }
            while (h <= t && f[q[t]] <= f[j]) --t;
            q[++t] = j;
            ++j;
        }
        while (h <= t && q[h] < l[i]) ++h;
        if (h <= t) f[i] = f[q[h]] + (i!=N+1 ? 1 : 0);
        else f[i] = -1;
    }
    cout << f[N+1] << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9886372.html

时间: 2024-11-08 14:21:06

P3084 [USACO13OPEN]照片Photo (dp+单调队列优化)的相关文章

[USACO13OPEN]照片Photo [动态规划 单调队列]

[USACO13OPEN]照片Photo 这题好烧脑... #include<bits/stdc++.h> using namespace std; #define ll long long #define rg register #define Max(x,y) ((x)>(y)?(x):(y)) #define Min(x,y) ((x)>(y)?(y):(x)) const int N=2e5+5,M=1e5+5,inf=0x3f3f3f3f,P=19650827; int

UESTC 594 我要长高 dp单调队列优化入门

//其实是个伪单调队列...渣渣刚入门 //戳这里:594 //dp[ i ][ j(现身高) ] = min(    dp[ i ][ k(现身高) ]  + fabs( j(现身高) - k(现身高) ) * C + ( j(现身高) - h[i](原身高) )  *( j(现身高) - h[i](原身高) )     ); 观察到可以单调队列优化,O(N * H * H)  —>  O(N * H) j >= k 时, dp[ i ][ j ] = min (    dp[ i ][ k

HDU 3401 Trade dp 单调队列优化

戳这里:3401 题意:给出第 i 天的股票买卖价格(APi,BPi),以及每天股票买卖的数量上限(ASi,BSi),要求任两次交易需要间隔 W 天以上,即第 i 天交易,第 i + W + 1 天才能再交易,求最多能赚多少钱 思路:dp[i][j] = max(dp[i - 1][j], max(dp[f][k] - (j - k) * APi[i]), max(dp[f][k] + (k - j) * BPi[i])); 从式子中观察出,若两天都持有股票数 j 时,之后的那一天所赚的钱不小于

【烽火传递】dp + 单调队列优化

题目描述 烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有 n 个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在 m 个烽火台中至少要有一个发出信号.现输入 n.m 和每个烽火台发出的信号的代价,请计算总共最少需要多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递! 输入格式 第一行有两个数 n,m 分别表示 n 个烽火台,在任意连续的 m 个烽火台中至少

[BZOJ2442][Usaco2011 Open]修剪草坪 dp+单调队列优化

2442: [Usaco2011 Open]修剪草坪 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1118  Solved: 569[Submit][Status][Discuss] Description 在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪.现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠. 然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作.FJ有N(1 <= N <= 100,0

vijos 1243 生产产品 DP + 单调队列优化

LINK 题意:有1个产品,m个步骤编号为1~m.步骤要在n个机器人的手中生产完成.其中,第i个步骤在第j个机器人手中的生产时间给定为$T[i][j]$,切换机器人消耗cost.步骤必须按顺序,同一个机器人不能连续完成超过l个步骤.求完成所有步骤的最短时间是多少.其中$m<=10^5$,$n<=5$,$l<=5*10^4$ 思路:这题用DP考虑易得一个转移方程$dp[i][j]=\min^{i-1}_{v=i-L}{(dp[v][x] + sum[i][j] - sum[v][j]) +

P3084 [USACO13OPEN]照片Photo

题目描述 农夫约翰决定给站在一条线上的N(1 <= N <= 200,000)头奶牛制作一张全家福照片,N头奶牛编号1到N. 于是约翰拍摄了M(1 <= M <= 100,000)张照片,每张照片都覆盖了连续一段奶牛:第i张照片中包含了编号a_i 到 b_i的奶牛.但是这些照片不一定把每一只奶牛都拍了进去. 在拍完照片后,约翰发现了一个有趣的事情:每张照片中都有一只身上带有斑点的奶牛.约翰意识到他的牛群中有一些斑点奶牛,但他从来没有统计过它们的数量. 根据照片,请你帮约翰估算在他的

hdu4362 dp + 单调队列优化

dp传输方程很easy需要 dp[i][j] = min{dp[i - 1][k] + abs(pos[i][j] -pos[i - 1][j]) + cost[i][j]} n行m一排 每个传输扫描m二级 干脆n*m*m 至O(10^7)    1500ms,能够暴力一试.姿势不正确就会TLE 事实上加上个内联函数求绝对值,同一时候赋值时候不使用min(a, b)  用G++交 就能够水过 正解是:由于每一个转移都是从上一层全部的状态開始转移.将上一层的状态依据pos排序 对当前状态的pos进

单调队列优化dp题目

附一链接,大多题型里面有,再附两题:https://blog.csdn.net/hjf1201/article/details/78729320 1.绿色通道 题目描述 Description <思远高考绿色通道>(Green Passage, GP)是唐山一中常用的练习册之一,其题量之大深受lsz等许多oiers的痛恨,其中又以数学绿色通道为最.2007年某月某日,soon-if (数学课代表),又一次宣布收这本作业,而lsz还一点也没有写-- 高二数学<绿色通道>总共有n道题目