zoukankan      html  css  js  c++  java
  • Codeforces 321E Ciel and Gondolas

    传送门:http://codeforces.com/problemset/problem/321/E

    【题解】

    首先有一个$O(n^2k)$的dp。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 4000 + 5;
    const int mod = 1e9+7;
    const ll inf = 1e17;
    
    inline int getint() {
        int x = 0; char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
        return x;
    }
    
    int n, K, a[N][N], d[N][N];
    ll f[805][N];
    
    int main() {
        n = getint(), K = getint();
        for (int i=1; i<=n; ++i)
            for (int j=1; j<=n; ++j)
                a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + getint();
        for (int i=1; i<=n; ++i) {
            d[i][i] = 0;
            for (int j=i+1; j<=n; ++j) 
                d[i][j] = (a[j][j] - a[j][i-1] - a[i-1][j] + a[i-1][i-1])/2;
        }
        for (int i=1; i<=n; ++i) f[0][i] = inf;
        for (int i=1; i<=K; ++i) {
            for (int j=1; j<=n; ++j) {
                f[i][j] = inf;
                for (int k=0; k<j; ++k)
                    f[i][j] = min(f[i][j], f[i-1][k] + d[k+1][j]);
            }
        }
        cout << f[K][n];
    
        return 0;
    }
    View Code

    然后发现每层当n向右移动的时候,决策点一定向右移动

    (可能可以观察+证明)

    然后用整体二分trick就可以了。复杂度$O(Knlogn)$。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10, N = 4000 + 5;
    const int mod = 1e9+7;
    const ll inf = 1e17;
    
    inline int getint() {
        int x = 0; char ch = getchar();
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
        return x;
    }
    
    int n, K, a[N][N], d[N][N];
    ll f[805][N], *F, *G;
    
    inline void solve(int l, int r, int al, int ar) {
        if(l > r) return ;
        int mid = l+r>>1; ll mx = inf, t; int pos = 0;
        for (int j=al; j<=ar && j<mid; ++j)  
            if((t = G[j] + d[j+1][mid]) < mx) mx = t, pos = j;
        F[mid] = mx;
        solve(l, mid-1, al, pos);
        solve(mid+1, r, pos, ar);
    }
        
    
    int main() {
        n = getint(), K = getint();
        for (int i=1; i<=n; ++i)
            for (int j=1; j<=n; ++j)
                a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + getint();
        for (int i=1; i<=n; ++i) {
            d[i][i] = 0;
            for (int j=i+1; j<=n; ++j) 
                d[i][j] = (a[j][j] - a[j][i-1] - a[i-1][j] + a[i-1][i-1])/2;
        }
        for (int i=1; i<=n; ++i) f[0][i] = inf;
        for (int i=1; i<=K; ++i) {
            F = f[i], G = f[i-1];
            solve(1, n, 0, n);
        }
        cout << f[K][n];
    
        return 0;
    }
    View Code
  • 相关阅读:
    AQS简介
    原子类案例
    保证线程安全的三个方面
    CAS无锁机制
    乐观锁与悲观锁
    读写锁简介
    重入锁简介
    并发队列Queue
    报错Cannot resolve com.mysq.jdbc.Connection.ping method. Will use 'SELECT 1' instead 问题记录
    Springboot中MyBatis 自动转换 map-underscore-to-camel-case
  • 原文地址:https://www.cnblogs.com/galaxies/p/cf321E.html
Copyright © 2011-2022 走看看