UOJ Ernd

斜率优化 优化DP ,单调栈维护凸包即可
坐标轴旋转变成二维数点的套路

%:pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 5;

struct Point {
    int x , y , id;
    friend bool operator < (Point xxx , Point yyy) {
        return (xxx.x == yyy.x) ? xxx.y < yyy.y : xxx.x < yyy.x;
    }
    void input(int k) {
        id = k; scanf("%d%d" , &x , &y); 
    }
}P[N] , Q[N];

bool cmp2(Point xxx , Point yyy) {
    if(xxx.x != yyy.x) return xxx.x < yyy.x;
    if(xxx.y != yyy.y) return xxx.y < yyy.y;
    return xxx.id < yyy.id;
}

int n , m , x , y , cnt;

map <int , int> Map , C;

#define lowbit(x) (x & (-x))

const double eps = 1e-12;

int chg[N] , pos[N];
long long f[N] , g[N] , S[N];

void add(int x , long long v) {
    for(int i = x;i < N;i += lowbit(i)) S[i] = max(S[i] , v);
}

long long sum(int x) {
    long long res = 0;
    for(int i = x;i;i -= lowbit(i)) res = max(res , S[i]);
    return res;
}

vector <int> Stk[N];

#define b(x , y) x[(int)x.size() - y]

long long sqr(long long x) {
    return x * x;
}

double calc(int a , int b) {
    int A = a - 1 , B = b - 1;
    return (double) (f[B + 1] - f[A + 1] - A * 1ll * A + B * 1ll * B) / 2. / (double)(B - A);
}

long long godance(int x) {
    int now = x - pos[x] + 1;
    //cerr << now << endl;
    if(!Stk[now].size()) {
        Stk[now].push_back(x); return 1;
    }
    while(Stk[now].size() > 1) {
        if(calc(b(Stk[now] , 2) , b(Stk[now] , 1)) <= x + eps) Stk[now].pop_back();
        else break;
    }
    long long res = f[b(Stk[now] , 1)] + sqr(x - b(Stk[now] , 1) + 1);
    //cerr << x <<" "<< b(Stk[now] , 1) << endl;
    while(Stk[now].size() > 1) {
        if(calc(b(Stk[now] , 2) , b(Stk[now] , 1)) <= calc(b(Stk[now] , 1) , x)) Stk[now].pop_back();
        else break;
    }
    Stk[now].push_back(x);
    return res;
}

main(void) {
    for(int i = scanf("%d" , &n);i <= n;++ i) P[i].input(i) , Q[i] = P[i] , Q[i].x = P[i].y + P[i].x , Q[i].y = P[i].y - P[i].x , ++ Map[Q[i].y];
    for(map<int , int> ::iterator it = Map.begin(); it != Map.end();++ it) {
        chg[++ cnt] = it -> first; C[it -> first] = cnt;
    }
    pos[1] = 1;
    for(int i = 2;i <= n;++ i) {
        if(abs(P[i].x - P[i - 1].x) <= abs(P[i].y - P[i - 1].y)) pos[i] = pos[i - 1] + 1;
        else pos[i] = 1;
    }
    for(int i = 1;i <= n;++ i) Q[i].y = C[Q[i].y];
    //for(int i = 1;i <= n;++ i) cerr << Q[i].y << endl;
    sort(Q + 1 , Q + n + 1 , cmp2);
    //for(int i = 1;i <= n;++ i) 
    long long ans = 0;
    for(int i = 1;i <= n;++ i) {
        int now = Q[i].id;
        f[now] = sum(Q[i].y);
        g[now] = godance(now);g[now] = max(g[now] , f[now] + 1);
        //for(int j = now - pos[now] + 1;j <= now;++ j) g[now] = max(g[now] , (now - j + 1) * (now - j + 1) + f[j]);
        ans = max(ans , f[now]); ans = max(ans , g[now]); 
        add(Q[i].y , g[now]);
    }
    cout << ans << endl;
}

出题人考察选手的基本优化DP能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值