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. }  
  • 相关阅读:
    poj 2763 Housewife Wind
    hdu 3966 Aragorn's Story
    poj 1655 Balancing Act 求树的重心
    有上下界的网络流问题
    URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
    ZOJ 2532 Internship 网络流求关键边
    ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
    SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流
    怎么样仿写已知网址的网页?
    5-10 公路村村通 (30分)
  • 原文地址:https://www.cnblogs.com/si--nian/p/10440012.html
Copyright © 2011-2022 走看看