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
*/

 

转载于:https://www.cnblogs.com/luoyibujue/p/9147206.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值