zoukankan      html  css  js  c++  java
  • ioi2016aliens

    /*
    首先考虑点在直线的两边效果一样 于是转移到一边
    之后发现当我们覆盖某些点时,有其他的一些点一定会被覆盖  我们找出所有必须覆盖的点
    之后我们发现我们找到的这些点 将其按照x递增排序 那么y也是递增的 
    然后我们 可以得到转移方程了 令dp[i][j]表示前i个都覆盖到了,用了j个正方形的最小花费
    
    然后我们考虑转移时的枚举dp[i][j] = min(dp[i][k] + (x[i] - y[k + 1] + 1) ^ 2;
     
    这个是显然NKN的, 斜率优化后NK, wqs二分后Nlogm 
    
    
    */
    
    
    //#include "aliens.h"
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector> 
    using namespace std;
    #define M 100010
    #define ll long long
    #define inf 0x3f3f3f3f
    struct Note{
        ll x, y;
        bool operator < (const Note &b) const{
            return this->x == b.x ? this->y > b.y : this->x < b.x;
        }
    }note[M], p[M];
    int tot,q[M],h,t, sm[M]; 
    ll dp[M], ans;
    
    
    double X(int x) {return p[x + 1].y;}
    double Y(int x) {return dp[x] - 2 * p[x + 1].y + p[x + 1].y * p[x + 1].y;}
    double slope(int x, int y) {return (Y(x) - Y(y)) / (X(x) - X(y));} 
    
    int solve(ll x)
    {
        h = 1, t = 1, q[1] = 0;
        for(int i = 1; i <= tot; i++)
        {
            while(h < t && 2.0 * p[i].x > slope(q[h], q[h + 1])) h++;
            dp[i] = dp[q[h]] + (p[i].x - p[q[h] + 1].y + 1) * (p[i].x - p[q[h] + 1].y + 1) + x;
            sm[i] = sm[q[h]] + 1;
            if(i == tot) break;
            if(p[i + 1].y <= p[i].x) dp[i] -= (p[i].x - p[i + 1].y + 1) * (p[i].x - p[i + 1].y + 1);
            while(h < t && slope(q[t], q[t - 1]) > slope(q[t], i)) t--;
            q[++t] = i; 
        }
        return sm[tot];
    }
    
    long long take_photos(int n, int m, int k, std::vector<int> r, std::vector<int> c) {
        for(int i = 0; i < n; i++) 
        {
            note[i].y = r[i], note[i].x = c[i];
            if(note[i].x < note[i].y) swap(note[i].x, note[i].y);
        }
        sort(note, note + n);
        for(int i = 1; i < n; i++)    
        {
            while(h <= t && note[i].y <= note[q[t]].y ) t--;
            q[++t] = i;
        }
        for(int i = h; i <= t; i++){tot++;p[tot].x = note[q[i]].x, p[tot].y = note[q[i]].y;}
        if((ans = solve(0)) <= k) {
            return dp[tot];
        }
        ll L = 0, R = 1ll * m * m + 10;
        while(L <= R)
        {
            ll mid = (L + R) >> 1;
            if(solve(mid) <= k) R = mid - 1, ans = dp[tot];
            else L = mid + 1;
        }
    //    if(ans - 1ll * R * k - k == 568367396612){solve(107455936237); return sm[tot];}
        return ans - 1ll * R * k - k;
    }
    /*
    5 7 2
    0 4 4 4 4 
    3 4 6 5 6
    
    2 6 2
    1 4
    4 1
    
    4 4 4
    1 0 2 2
    3 1 1 2
    
    1 3
    0 1
    2 1
    2 2
    */
  • 相关阅读:
    POJ2142:The Balance——题解
    POJ1061:青蛙的约会——题解
    接口测试结束后的小结
    接口测试结束后的小结
    如何进行需求测试/需求评审
    如何进行需求测试/需求评审
    测试人员掌握代码的重要性
    测试人员掌握代码的重要性
    测试人员掌握代码的重要性
    软件自动化测试开发-开班啦
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/9147206.html
Copyright © 2011-2022 走看看