zoukankan      html  css  js  c++  java
  • Watching Fireworks is Fun

    题目链接:http://codeforces.com/problemset/problem/372/C

    题意:城镇中有 n个位置,有 m个烟花要放。第 i个烟花放出的时间记为t[i],放出的位置记为 a[i]。如果烟花放出的时候,你处在位置 j,那么你将收获b[i]-abs(j-a[i])  点快乐值。

    初始你可在任意位置,你每个单位时间可以移动不大于 d个单位距离。现在你需要最大化你能获得的快乐值。

    思路:设dp[i][j] 表示在放第 i 个烟花时,你的位置在 j 所能获得的最大快乐值。状态转移方程 : dp[i][j]=max(dp[i-1][k])+b[i]-abs(a[i]-j);

    由于n较大,直接这样dp肯定会超时,但可以用单调队列优化,时间复杂度变为O(n*m)。我们在计算一个新的 i 的状态值时候只需将原来的 dp[i-1] 构造成一个单调队列,并维护单调队列,使得其能在均摊O(1) 的时间复杂度内计算出 的值max(dp[i-1][k]),从而根据公式计算出 dp[i][j] 的值。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf = 0xcfcfcfcfcfcfcfcf;
    ll dp[2][200005];
    ll a[310],b[310],t[310];
    int que[200005];
    int main()
    {
        int n,m,d;
        cin>>n>>m>>d;
        for(int i=1;i<=m;i++)
            cin>>a[i]>>b[i]>>t[i];
        memset(dp,inf,sizeof(dp));
        memset(que,0,sizeof(que));
        for(int i=1;i<=n;i++)
            dp[0][i]=0;
        int k=1;
        for(int i=1;i<=m;i++)
        {
            int l=1,r=0;
            int h=1;
            for(int j=1;j<=n;j++)
            {
                for( ; h<=min(1ll*n,j+d*(t[i]-t[i-1]));h++)
                {
                    while(l<=r&&dp[k^1][que[r]]<=dp[k^1][h])
                        r--;
                    que[++r]=h;
                }
                while(l<=r&&que[l]<min(1ll*n,j-d*(t[i]-t[i-1])))
                    l++;
                dp[k][j] = dp[k^1][que[l]]-abs(a[i]-j)+b[i];
            }
            k=k^1;
        }
        ll ans=inf;
        for(int i=1;i<=n;i++)
            ans=max(ans,dp[k^1][i]);
        cout<<ans<<endl;
    }
  • 相关阅读:
    固态硬盘 每秒1.5G
    editPlus
    juqery 插入一行
    BufferedReader读取UTF8文件中文乱码
    jquery table 操作
    noSql
    javascript 开发规范
    同一服务器上安装多个tomcat
    100 个搜索引擎
    firefox 开发sdk
  • 原文地址:https://www.cnblogs.com/zcb123456789/p/13752174.html
Copyright © 2011-2022 走看看