zoukankan      html  css  js  c++  java
  • FJWC2019 全连

    题目描述

    n个音符,第i个音符会在第i个时刻来临

    令第 i 个音符的准备时间为 ti 个单位时间,如果选择去点击第 i 个音符,那么就没法点击所有到来时刻在 (iti ,i+ti)中的音符。

    每一个音符有一个权值,求一种点击方法使得权值和最高(N<=1e6)

    Solution

    首先先考虑最暴力的dp,令dp[i]表示我点到第i个时刻时,可以达到的最大权值

    那么转移就很显然了

    dp[i]=max(dp[j=1..i])+a[j](j+t[j]<=i&&i-t[i]>=j)

    这个dp显然是O(n^2)这时候我们发现每次循环1..i的过程十分的浪费时间所以我们来考虑优化这个过程

    可以发现这是个二维偏序问题,一般的套路是一维排序另一维用数据结构去维护

    因为i是递增的,这时候我们把所有的音符按照i+t[i]排序,并且用一个线段树维护区间内dp的最大值

    为了满足j+t[j]<=i 我们在当前时刻>当前最小的i+t[i]的时候才把最小的imodify进线段树里

    每次查询的时候就只要查询1..i-t[i]的最大dp然后只用最大dp值转移过来就可以了

    这是一个O(N log N)的效率[因为评测姬跑的很快所以O(N log^2 N)跑过去了…]

    Code

    1. //考场代码...结果脑子一抽考场上用了堆维护第一维关系... 所以这个代码效率是O(N log^2 N)  
    2. #include <bits/stdc++.h>  
    3. #define pa pair<long long,long long>  
    4. using namespace std;  
    5. inline long long read(){  
    6.    long long s=0,w=1;  
    7.    char ch=getchar();  
    8.    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}  
    9.    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();  
    10.    return s*w;  
    11. }  
    12. int N;  
    13. long long Tree[4005005];  
    14. void Change(int Now,int K,int l,int r,long long Ned)  
    15. {  
    16.     int mid=(l+r)/2;  
    17.     if (l==r&&l==K)  
    18.     {  
    19.       Tree[Now]=Ned;  
    20.       return;  
    21.     }  
    22.     if (K<=mid)  
    23.      Change(Now*2,K,l,mid,Ned);  
    24.     if (mid<K)  
    25.      Change(Now*2+1,K,mid+1,r,Ned);  
    26.     Tree[Now]=max(Tree[Now*2],Tree[Now*2+1]);  
    27. }  
    28. long long query(int Now,int L,int R,int l,int r)  
    29. {  
    30.     int mid=(l+r)/2;  
    31.     if (L<=l&&r<=R)  
    32.       return Tree[Now];  
    33.     long long qwqq=0;  
    34.     if (L<=mid)  
    35.     qwqq=max(query(Now*2,L,R,l,mid),qwqq);  
    36.     if (mid<R)  
    37.     qwqq=max(query(Now*2+1,L,R,mid+1,r),qwqq);  
    38.     return qwqq;  
    39. }  
    40. long long dp[1000005],a[1000005],t[1000005],Score[1000005];  
    41. priority_queue<pa,vector<pa>,greater<pa> > qwqq;  
    42. int main()  
    43. {  
    44.     freopen("fc.in","r",stdin);  
    45.     freopen("fc.out","w",stdout);  
    46.     N=read();  
    47.     for (int i=1;i<=N;i++)  
    48.       t[i]=read();  
    49.     for (int i=1;i<=N;i++)  
    50.       a[i]=read();  
    51.     for (int i=1;i<=N;i++)  
    52.       Score[i]=a[i]*t[i];  
    53.     for (int i=1;i<=N;i++)  
    54.     {  
    55.         pa r;  
    56.         if (!qwqq.empty()) r=qwqq.top();  
    57.         while (!qwqq.empty()&&r.first<=i)  
    58.          {  
    59.             Change(1,r.second,1,N,dp[r.second]);  
    60.             qwqq.pop();  
    61.             r=qwqq.top();  
    62.          }  
    63.         long long  R=0;  
    64.         if (i-t[i]>0)  
    65.         R=query(1,1,i-t[i],1,N);  
    66.         dp[i]=R+Score[i];  
    67.         pa Now;  
    68.         Now.first=i+t[i];  
    69.         Now.second=i;  
    70.         qwqq.push(Now);  
    71.     }  
    72.     long long ans=0;  
    73.     for (int i=1;i<=N;i++)  
    74.       ans=max(ans,dp[i]);  
    75.     printf("%lld",ans);  
    76.     return 0;  
    77. }  
  • 相关阅读:
    MVC 后台DataTable 前台遍历
    oracle 创建表空间详细介绍
    C# Chart 折线图 多条数据展示
    ASP.NET Request.QueryString 出现乱码问题
    生成XML文件
    什么是Intent(意图)
    HTTP错误405-Method Not Allowed
    通过剪切板传递数据—— 传递一个对象
    Linux下crontab命令的用法
    Redis使用介绍
  • 原文地址:https://www.cnblogs.com/si--nian/p/10440012.html
Copyright © 2011-2022 走看看