zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P7302】[NOI1998]免费馅饼

    链接:

    题目

    博客园

    题目大意:

    (n) 个馅饼,第 (i) 个馅饼在 (t_i) 时掉落在 (p_i) 上,若掉落时玩家不没接住,馅饼就会消失。接住第 (i) 个馅饼能获得 (v_i) 的分数,问如何使得分数之和最大。

    正文:

    考虑用动态规划。设 (f_i) 表示前 (i) 个馅饼接住了第 (i) 个的最大分数。我们可以列方程得:

    [f_i=max_{ ext{abs}(p_i-p_j)leq 2(t_i-t_j)}{f_j+v_i} ]

    直接 (mathcal{O}(n^2)) 是不可行的,考虑优化,展开上式的条件:

    [left{egin{matrix} p_i+2t_ileq p_j+2t_j&(p_ileq p_j)\ p_i-2t_ileq p_j-2t_j&(p_i> p_j) end{matrix} ight.]

    因为有两个关键字,按照关于第一个式子的关键字排序,用关于第二个式子的关键字树状数组维护就好了(或者用第二个式子排序,第一个式子树状数组,顺序没影响)。

    代码:

    const int N = 1e5 + 10;
    
    ll t[N], b[N];
    int n, m, k;
    
    void modify(int x, ll val){for (; x <= k; x += x & -x) t[x] = max(t[x], val);}
    ll query (int x)
    {
    	ll ans = 0;
    	for (; x; x -= x & -x) ans = max(ans, t[x]);
    	return ans;
    }
    
    struct node
    {
    	ll l, r, p, t;
    	int v;
    }a[N];
    
    bool cmp1 (node a, node b) {return a.r < b.r;}
    bool cmp2 (node a, node b) {return a.l < b.l;}
    
    int main ()
    {
    	scanf ("%d%d", &m, &n);
    	for (int i = 1; i <= n; i++)
    		scanf ("%d%d%d", &a[i].t, &a[i].p, &a[i].v), 
    		a[i].l = 2 * a[i].t - a[i].p, 
    		a[i].r = 2 * a[i].t + a[i].p,
    		b[i] = a[i].r;
    	sort (a + 1, a + 1 + n, cmp1);
    	sort (b + 1, b + 1 + n);
    	k = unique(b + 1, b + 1 + n) - b;
    	for (int i = 1; i <= n; i++)
    		a[i].r = lower_bound(b + 1, b + 1 + n, a[i].r) - b;
    	sort (a + 1, a + 1 + n, cmp2);
    	for (int i = 1; i <= n; i++)
    	{
    		ll tmp = query(a[i].r);
    		modify(a[i].r, tmp + a[i].v);
    	}
    	printf ("%lld
    ", query(k));
    	
    	return 0;
    }
    
  • 相关阅读:
    10,EasyNetQ-发布确认
    9,EasyNetQ-版本化消息
    一个小程序云开发的项目,图书借还系统
    利用canvas对图片进行切割
    微信小程序添加卡券到微信卡包,使用wx.addCard()方法传参及整体流程
    git合并时忽略某个文件
    小程序接入云通信IM
    小程序插件使用wx.createSelectorQuery()获取不到节点信息
    小程序插件开发流程及注意事项
    小米6使用charles抓包https
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14336793.html
Copyright © 2011-2022 走看看