zoukankan      html  css  js  c++  java
  • codeforces 455E

    题目:http://codeforces.com/problemset/problem/455/E

    题意:给定数组a,及f的定义:

            f[1][j] = a[j];  1 <= j <= n

            f[i][j] = min(f[i-1][j-1], f[i-1][j]) + a[j];  2 <= i <= j <= n

     给定q个询问,每个询问为l,r,求f[l][r]

    My solution:

    1.  写一些小数据就可以发现,其实对于一个询问l,r,其实等价于:

                  从[r-l+1, r]这个区间内取l个数,使其和最小。但是比较特殊的是,一个数可以取多次,并且如果取了一个x,那么[x+1,r]间的所有数必须得取。

                 例如,对于n=3, a = {2, 1, 3}

                 询问l=3, r=3的取法有:3+3+3=9, 3+3+1=7, 3+1+1=5, 3+1+2= 6;答案为3+1+1=5

         2.设答案f[l][r]的询问答案合法区间是在[x, r]这一段取得的,我们还可以发现如下的性质:

              1)a[x]一定是[x,r]中最小的,否则存在 x<=y<=r, a[y] <= a[x],比[x,r]更优的区间[y, r]

                 除[y, r]的共同区间外,剩下的l-y-r个[y,r]区间可以全取a[y],显然比[x,r]更小

              2)a[x+1]~a[y]各取一个,剩下的全取a[x],因为a[x]是区间最小元素,取越多答案越小

          3.基于2我们可以维护一个递增的序列来求答案,但是这样还是不够,妥妥TlE

            只能看下决策之间有什么关系了;

            对于询问(l,r)不妨设两个决策k<j,并且决策k优于j

            那么 (sum[r] - sum[k]) - (l - (r - k)) * a[k] <= (sum[r] - sum[j]) - (l - (r - j)) * a[j];

            整理一下式子:

                      (sum[k] - a[k]*k) - (sum[j] - a[j]*j) / (a[k] - a[j]) <= l - r;

            这不就是个斜率的式子,剩下的就是维护一个凸壳即可

            4.具体的话对于询问按照r排序,然后离线做

               然后二分一左边界,找到合法区间完,再二分找到合法的斜率。具体看代码吧

    code:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <string>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <cstdlib>
     9 #include <sstream>
    10 #include <fstream>
    11 #include <list>
    12 #include <deque>
    13 #include <queue>
    14 #include <stack>
    15 #include <map>
    16 #include <set>
    17 #include <bitset>
    18 #include <cctype>
    19 #include <ctime>
    20 #include <utility>
    21 #define M0(x) memset(x, 0, sizeof(x))
    22 #define pb push_back
    23 #define mp make_pair
    24 #define x first
    25 #define y second
    26 #define vii vector< pair<int, int> >::iterator 
    27 using namespace std;
    28 const int maxn = 100010;
    29 vector< pair<int, int> > ask[maxn];
    30 int n, m;
    31 long long sum[maxn], ans[maxn];
    32 int s[maxn], top, a[maxn];
    33 
    34 inline double slope(int k, int j){
    35       double yk = sum[k] - (double)k * a[k], yj = sum[j] - (double)j * a[j];
    36       return (yk - yj) / (a[k] - a[j]);
    37 }
    38 
    39 void init(){
    40     for (int i = 1; i <= n; ++i)
    41         scanf("%d", a+i), sum[i] = sum[i-1] + a[i];
    42     for (int i = 0; i <= n; ++i) ask[i].clear();
    43     scanf("%d", &m);
    44     int l, r;
    45     for (int i = 0; i < m; ++i){
    46          scanf("%d%d", &l, &r);
    47          ask[r].pb(mp(l, i));
    48     }
    49 }
    50 
    51 void solve(){
    52     int top = 0;
    53     int l, r, mid, pos;
    54     for (int i = 1; i <= n; ++i){
    55           while (top > 0 && a[s[top]] >= a[i]) --top;
    56           while (top > 1 && slope(s[top], i) >= slope(s[top-1], i)) --top;
    57           s[++top] = i;
    58           for (vii it = ask[i].begin(); it != ask[i].end(); ++it){
    59                 l = lower_bound(s+1, s+top+1, i-it->x+1) - s;
    60                 r = top-1, pos = i;
    61                 while (l <= r){
    62                       mid = (l + r) >> 1;
    63                       if (slope(s[mid], s[mid+1]) <= it->x - i) pos = s[mid], r = mid - 1;
    64                       else l = mid + 1;
    65                 }
    66                 ans[it->y] = sum[i] - sum[pos] + (long long)a[pos]*(it->x+pos-i);
    67           }    
    68     }
    69     for (int i = 0; i < m; ++i)
    70        printf("%I64d
    ", ans[i]); 
    71 }
    72 int main(){
    73 //    freopen("a.in","r",stdin);
    74 //    freopen("a.out","w",stdout);
    75     while (scanf("%d", &n) != EOF){
    76         init();
    77         solve();
    78     }
    79     return 0;
    80 }
    View Code

      

          

  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/yzcstc/p/3963351.html
Copyright © 2011-2022 走看看