zoukankan      html  css  js  c++  java
  • LA 4327 多段图

    题目链接:https://vjudge.net/contest/164840#problem/B

    题意:

    从南往北走,横向的时间不能超过 c;

    横向路上有权值,求权值最大;

    分析:

    n<=100,m<=10000

    数据范围很大了,基本上要n*m;

    分析每个交叉路口,每个交叉路口,可以从下一行的左边,或者下一行的右边过来;

    那么这个交叉路口就是max(L[j],R[j]);

    怎么得到,某一个交叉路口从左边来,可以有哪些点呢? 不可能循环跑一遍(m的范围);

    就用了一个Q双端队列来维护;

    怎么得到,从哪个点上来最优呢? 在这个队列中的点也不能循环跑一遍;

    还是利用这个队列;维护他这个队列是单调队列就好了,

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define LL long long
     6 
     7 const int maxn = 105;
     8 const int maxm = 10100;
     9 LL f[maxn][maxm],t[maxn][maxm],L[maxm],R[maxm],n,m,c,d[maxn][maxm];
    10 
    11 deque<int> Q;
    12 int Lfunc(int j,int i) {
    13     return d[i-1][j] - f[i][j];
    14 }
    15 
    16 int Rfunc(int j,int i) {
    17     return d[i-1][j] + f[i][j];
    18 }
    19 
    20 int main() {
    21     while(scanf("%lld %lld %lld",&n,&m,&c)==3&&n) {
    22         for(int i=1; i<=n+1; i++)
    23             for(int j=0; j<=m; j++) {
    24                 if(!j) f[i][j] = 0;
    25                 else {
    26                     scanf("%lld",&f[i][j]);
    27                     f[i][j]+=f[i][j-1];
    28                 }
    29             }
    30 
    31 
    32         for(int i=1; i<=n+1; i++)
    33             for(int j=1; j<=m; j++) {
    34                 if(!j) t[i][j] = 0;
    35                 else {
    36                     scanf("%lld",&t[i][j]);
    37                     t[i][j]+=t[i][j-1];
    38                 }
    39             }
    40 
    41 
    42         for(int i=0; i<=m; i++)
    43             d[0][i] = 0;
    44 
    45         for(int i=1; i<=n+1; i++) {
    46             L[0] = d[i-1][0];
    47             Q.clear();
    48             Q.push_back(0);
    49             for(int j=1; j<=m; j++) {
    50                 while(!Q.empty()&&t[i][j]-t[i][Q.front()]>c) {
    51                     Q.pop_front();
    52                 }
    53                 L[j] = d[i-1][j];   //从左到达 j 的最优值
    54                 if(!Q.empty()) L[j] =max(L[j],Lfunc(Q.front(),i)+f[i][j]);
    55                 while(!Q.empty()&&Lfunc(Q.back(),i)<=Lfunc(j,i)) Q.pop_back();
    56                 Q.push_back(j);
    57             }
    58             
    59             
    60             R[0] = d[i-1][m];
    61             Q.clear();
    62             Q.push_back(m);
    63             for(int j=m-1; j>=0; j--) {
    64                 while(!Q.empty()&&t[i][Q.front()]-t[i][j]>c) Q.pop_front();
    65                 R[j] = d[i-1][j];
    66                 if(!Q.empty()) R[j] = Rfunc(Q.front(),i)-f[i][j];
    67                 while(!Q.empty()&&Rfunc(Q.back(),i)<=Rfunc(j,i)) Q.pop_back();
    68                 Q.push_back(j);
    69             }
    70             for(int j=0; j<=m; j++)
    71                 d[i][j] = max(L[j],R[j]);
    72         }
    73         
    74         LL res;
    75         for(int i=0; i<=m; i++) {
    76             if(!i) res=d[n+1][i];
    77             else res = max(d[n+1][i],res);
    78         }
    79         printf("%lld
    ",res);
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    HDU 2852 KiKi's K-Number (主席树)
    HDU 2089 不要62
    Light oj 1140 How Many Zeroes?
    Bless You Autocorrect!
    HDU 6201 transaction transaction transaction
    HDU1561 The more ,The better (树形背包Dp)
    CodeForces 607B zuma
    POJ 1651 Mulitiplication Puzzle
    CSUOJ 1952 合并石子
    Uva 1599 Ideal path
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6896581.html
Copyright © 2011-2022 走看看