1 条题解

  • 0
    @ 2021-11-06 20:38:16

    75pts:
    可以暴力。
    时间复杂度\(O(n^2m^2k)\)
    175pts:
    运用二维前缀和的思想即可。
    时间复杂度\(O(mnk)\)
    300pts:
    我们实际是在维护一些一次函数,对于各个点 \(x\) 快速求出\(max_{f_i(x)}\)
    而最后能产生贡献的,即处在最上方的那些线段,一定是一个凸包的形状。

    所以,我们按照各个一次函数的斜率\(k\)排序,维护这个凸包即可。
    时间复杂度是\(O((nm)\log (nm) + k)\)

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long int
    
    ll a[2005][2005], b[2005][2005], pref_a[2005][2005], pref_b[2005][2005], ans[1000005];
    int n,m,r,c,t;
    const ll maxt = 1e6+10;
    ll f(ll k, ll b, ll x){return k*x+b;}
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) cin>>a[i][j];
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) cin>>b[i][j];
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) 
        {
            pref_a[i][j] = pref_a[i-1][j] + pref_a[i][j-1] + a[i][j] - pref_a[i-1][j-1];
            pref_b[i][j] = pref_b[i-1][j] + pref_b[i][j-1] + b[i][j] - pref_b[i-1][j-1];
        }
        cin>>r>>c>>t;
        vector<pair<ll,ll>> linear_functions;
        for(int i=1;i<=n-r+1;i++) for(int j=1;j<=m-c+1;j++)
            linear_functions.push_back(make_pair(
                pref_b[i+r-1][j+c-1] + pref_b[i-1][j-1] - pref_b[i-1][j+c-1] - pref_b[i+r-1][j-1],
                pref_a[i+r-1][j+c-1] + pref_a[i-1][j-1] - pref_a[i-1][j+c-1] - pref_a[i+r-1][j-1]
                ));
        sort(linear_functions.begin(), linear_functions.end());
        vector<tuple<ll,ll,ll>> convex_hull; 
        convex_hull.push_back(make_tuple(0, linear_functions.begin()->first, linear_functions.begin()->second));
        linear_functions.erase(linear_functions.begin());
        for(auto it:linear_functions)
        {
            while(!convex_hull.empty())
            {
                ll index, k, b;
                tie(index, k, b) = convex_hull.back();
                if(f(k,b,t)>=f(it.first, it.second, t)) goto outer;
                if(f(k,b,index) <= f(it.first, it.second, index))
                    convex_hull.pop_back();
                else break;
            }
            if(convex_hull.empty()) convex_hull.push_back(make_tuple(0, it.first, it.second));
            else convex_hull.push_back(make_tuple(max(0.0, ceil(
                (it.second - get<2>(convex_hull.back())) * 1.0 / (get<1>(convex_hull.back()) - it.first))
            ),it.first, it.second)); // k_1 x + b_1 = k_2 x + b_2
            outer:;
        }
        for(int i = 0; i < convex_hull.size(); i++)
        {
            int k = (i==convex_hull.size()-1 ? t : get<0>(convex_hull[i+1]));
            for(int j = get<0>(convex_hull[i]); j < k; j++)
                ans[j] = get<1>(convex_hull[i]) * j + get<2>(convex_hull[i]);
        }
        for(int i = 0; i < t; i++) cout<<ans[i]<<'\n';
        return 0;
    }
    

    顺便一提,本题是 "P4254[JSOI2008]Blue Mary开公司" 的简单版本。如果需要强制在线,可以采用Li-Chao Segment tree解决。

  • 1

信息

ID
1302
难度
8
分类
(无)
标签
递交数
24
已通过
3
通过率
12%
被复制
1
上传者