• Codeforces 721E DP


    大概思路及题意看这篇博客

    我的理解:设f[i]表示处理到第i个区间,能唱的最多的歌,g[i]是保证f[i]最大时最靠左的点。那么f[i] = max(f[j] + (r[i] - max(l[i], g[j] + t)) / p), g[i] = r[i] - (r[i] - max(l[i], g[j] + t)) % p);容易发现, f[i]和g[i]是单增的,所以有很多状态是不可能转移的。只有在两个位置之间的状态才有可能更新状态。1:g[j] + t <= [i]的最大的j。2:g[j] + t <= r[i]的最大的j。在这之间的状态有可能会对状态产生影响,我们需要一个个出队,去更新状态,这样有很多的状态出队了,大大降低了时间复杂度。需要注意,第二个位置的状态在出队之后还需要入队,因为它可能成为i + 1状态的1位置。

    代码:

    #include <bits/stdc++.h>
    #define pii pair<int, int>
    using namespace std;
    const int maxn = 100010;
    int f[maxn], g[maxn];
    int q[maxn];
    pii a[maxn];
    int main() {
    	int L, n, p, t;
    	scanf("%d%d%d%d", &L, &n, &p, &t);
    	for (int i = 1; i <= n; i++)
    		scanf("%d%d", &a[i].first, &a[i].second);
    	int l = 1, r = 0;
    	g[0] = -t;
    	for (int i = 1; i <= n; i++) {
    		f[i] = f[i - 1];
    		g[i] = g[i - 1];
    		l--;
    		while(l <= r && g[q[l]] + t <= a[i].second) {
    			int x = max(a[i].first, g[q[l]] + t);
    			int y = f[q[l]] + (a[i].second - x) / p;
    			int z = a[i].second - (a[i].second - x) % p;
    			if(y > f[i] || (y == f[i] && g[i] > z)) {
    				f[i] = y;
    				g[i] = z;
    			}
    			l++;
    		}
    		q[++r] = i;
    	}
    	printf("%d
    ", f[n]);
    } 
    

      

  • 相关阅读:
    四则运算生成器
    学习进度总结
    大三寒假实习内容
    构建之法一二章读后感
    构建之法第三章读后感
    关于NopCommerce3.6版用户登录详解
    关于NopCommerce3.6版的@Html.Widget(“home_page_top”)的说明
    Java学习心得(2)
    Java学习心得(5)
    Java学习心得(6)
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10759678.html
Copyright © 2020-2023  润新知