noi.ac #289. 电梯(单调队列)

题意

题目链接

Sol

傻叉的我以为给出的\(t\)是单调递增的,然后\(100\rightarrow0\)

首先可以按\(t\)排序,那么转移方程为

\(f[i] = min_{j=0}^{i-1}(max(t[i], f[j]) + 2 * max_{k=j+1}^i x[k])\)

不难发现,若\(i < j\)且\(x[i] < x[j]\),那么从\(i\)转移过来一定是不优的,一定是从\(i\)之前的某个位置转移过来。(f单增)

然后直接单调队列搞一搞就行了,

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define fi first
#define se second
#define LL long long
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
char buf[(1 << 22)], *p1 = buf, *p2 = buf;
using namespace std;
const int MAXN = 1e6 + 10;
template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;}
template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, q[MAXN], val[MAXN], top;
LL f[MAXN];
Pair a[MAXN];
signed main() {
    N = read();
    for(int i = 1; i <= N; i++) a[i].fi = read(), a[i].se = read();
    sort(a + 1, a + N + 1);
    for(int i = 1; i <= N; i++) {
        while(top && a[i].se > a[top].se) top--;
        a[++top] = a[i];
    }
    memset(f, 0x7f, sizeof(f));
    N = top; f[0] = 0;
    int l = 1, r = 0, las = 0;
    for(int i = 1; i <= N; i++) {
        while(l <= r && a[i].fi >= f[q[l]]) las = q[l++];
        if(las < i) chmin(f[i], a[i].fi + 2ll * a[las + 1].se);
        if(l <= r) chmin(f[i], val[l]);
        int cur = f[i] + 2ll * a[i + 1].se;
        while(l <= r && cur <= val[r]) r--;
        q[++r] = i; val[r] = cur;
    }
    cout << f[N];
    return 0;
}

原文地址:https://www.cnblogs.com/zwfymqz/p/10590303.html

时间: 2024-10-08 00:15:09

noi.ac #289. 电梯(单调队列)的相关文章

【POJ 2823 Sliding Window】 单调队列

题目大意:给n个数,一个长度为k(k<n)的闭区间从0滑动到n,求滑动中区间的最大值序列和最小值序列. 最大值和最小值是类似的,在此以最大值为例分析. 数据结构要求:能保存最多k个元素,快速取得最大值,更新时删去“过期”元素和“不再有希望”的元素,安放新元素. 单调队列的基本概念百度百科讲得比较清楚了:http://baike.baidu.com/view/3771451.htm 我的大致思路是: 1. 每个元素存储为结构体,包含它的秩和值.维护最大长度为k的单调队列,保证所有元素的秩都在区间内

POJ2823 Sliding Window(单调队列)

单调队列,我用deque维护.这道题不难写,我第二次写单调队列,1次AC. ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<deque> #define rep(i,r) for(int i=0;i<r;i++) #define clr(x,c) memset

POJ 3162 Walking Race (树的直径,单调队列)

题意:给定一棵带边权的n个节点的树,首先要求出每个点的最长路,然后写成序列d[1],d[2]...d[n],然后求满足 区间最大值-区间最小值<=k 的最大区间长度为多少? 思路: 分两步进行: (1)最多仅需3次DFS就可以在O(n)时间内求出每个点的最长路了.先从任意点t出发遍历过有点,记录下从点t出发到每个点的最长路,然后从记录的其中一个距t最远的点root出发,再一次DFS,就可以得到离root最远的点e啦,再从e出发DFS一次,就得到所有点的最长路了.注意3次DFS的代码都是一样的喔~

woj 1575 - Signal generators 单调队列优化dp + 瞎搞

戳这里:1575 题意:直线上排列着N个信号发射器,每个信号发射器被激活后将会使得影响范围内的所有发射器都被激活.询问激活任意一个发射器后被激活的发射器数最大是多少. 官方题解:可能会存在环的情况,考虑按坐标排序后i < j < k,j激活了k,然后k再激活i.但是这样可以转化为直接激活k的方案.所以无影响. 于是可以用dp求解.dp[i] = max( dp[j] + 1 ), position[j] + R[i] >= position[i],用单调队列优化时间复杂度为O(n). 向

poj 3017 Cut the Sequence(单调队列优化 )

题目链接:http://poj.org/problem?id=3017 题意:给你一个长度为n的数列,要求把这个数列划分为任意块,每块的元素和小于m,使得所有块的最大值的和最小 分析:这题很快就能想到一个DP方程 f[ i ]=min{ f[ j ] +max{ a[ k ] }}( b[ i ]<j<i,j<k<=i)     b[ i ]到 i的和大于m 这个方程的复杂度是O(n^2),明显要超时的(怎么discuss都说数据弱呢= =) 然后是优化了,首先当然是要优化一个最大

使用单调队列优化的 O(nm) 多重背包算法

我搜索了一下,找到了一篇很好的博客,讲的挺详细:链接. 解析 多重背包的最原始的状态转移方程: 令 c[i] = min(num[i], j / v[i]) f[i][j] = max(f[i-1][j-k*v[i]] + k*w[i])     (1 <= k <= c[i])  这里的 k 是指取第 i 种物品 k 件. 如果令 a = j / v[i] , b = j % v[i] 那么 j = a * v[i] + b. 这里用 k 表示的意义改变, k 表示取第 i 种物品的件数比

【单调队列优化dp】uestc 594 我要长高

http://acm.uestc.edu.cn/#/problem/show/594 [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=5e4+2; 5 const int inf=0x3f3f3f3f; 6 int n,c; 7 int cur; 8 int dp[2][maxn]; 9 int q[maxn]; 10 int main() 11 { 1

hdu3706单调队列

很基础的单调队列 #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<cassert> #include<iomanip> #include<cstdlib> #include<cstring>

Vijos P1243 生产产品 (单调队列优化DP)

题意: 必须严格按顺序执行M个步骤来生产一个产品,每一个步骤都可以在N台机器中的任何一台完成.机器i完成第j个步骤的时间为T[i][j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完成了产品的L个步骤,下一个步骤就必须换一台机器来完成.问一个产品最短需要多长时间呢?(对于100%的数据,N<=5, L<=50000,M<=100000) 题意: 被高中生虐了~ 题意要求尽量缩短时间来完成一件产品,但是由于需