题目大意:
3<=m<=n<=1e5
题解:
显然是C由小到大是最优的,那么这时代价就是(最大-最小)*2
先把把所有蛋糕按c排序。
不然发现随着左端点的递增,最优决策的右端点是非递减的。
然后这个东西居然可以分治???(套路太浅)
设 d g ( x , y , l , r ) dg(x,y,l,r) dg(x,y,l,r)表示现在要搞左端点在 [ x , y ] [x,y] [x,y]里的,它们可能的最优决策区间是 [ l , r ] [l,r] [l,r]
设 m = ( x + y ) / 2 m=(x+y)/2 m=(x+y)/2,m的最优决策点是u,这个可以通过暴力扫描 [ l , r ] [l,r] [l,r]得到。
那么 d g ( x , m − 1 , l , u ) , d g ( m + 1 , y , u , r ) dg(x,m-1,l,u),dg(m+1,y,u,r) dg(x,m−1,l,u),dg(m+1,y,u,r)
假设query一次的复杂度是 O ( 1 ) O(1) O(1)的,那么这个做法的复杂度是 O ( n l o g n ) O(n~log~n) O(n log n)的。
可以这么分析,每一层的query次数最多是 O ( n + 段 数 ) = O ( n ) O(n+段数)=O(n) O(n+段数)=O(n)的,一共有 O ( l o g n ) O(log~n) O(log n)层
query可以通过预处理一个主席树来线段树二分前V前 m − 2 m-2 m−2大的和来做
总复杂度是 O ( n l o g 2 n ) O(n~log^2~n) O(n log2 n)
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 2e5 + 5;
int n, m;
struct P {
ll x, y;
P(ll _x = 0, ll _y = 0) { x = _x, y = _y;}
} a[N];
int cmp(P a, P b) { return a.y < b.y;}
P operator + (P a, P b) { return P(a.x + b.x, a.y + b.y);}
P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}
int b[N], tb[N];
int cmp2(int x, int y) { return a[x].x < a[y].x;}
struct tree {
int l, r;
P a;
} t[N * 30];
#define i0 t[i].l
#define i1 t[i].r
int g[N], pl, pr, tot;
void add(int &i, int x, int y) {
if(y < pl || x > pr) return;
t[++ tot] = t[i]; i = tot;
if(x >= pl && y <= pr) {
t[i].a = P(1, a[b[x]].x);
return;
}
int m = x + y >> 1;
add(i0, x, m); add(i1, m + 1, y);
t[i].a = t[i0].a + t[i1].a;
}
P px;
void ft(int g1, int g2, int x, int y) {
if(x == y) {
if(pl - px.x > 0) px = px + t[g2].a - t[g1].a;
return;
}
int m = x + y >> 1;
int r1 = t[g1].r, r2 = t[g2].r;
if((t[r2].a - t[r1].a).x <= pl - px.x) {
px = px + t[r2].a - t[r1].a;
ft(t[g1].l, t[g2].l, x, m);
} else ft(r1, r2, m + 1, y);
}
ll query(int x, int y) {
px = P(0, 0); pl = m - 2;
ft(g[x], g[y - 1], 1, n);
return px.y + -2 * (a[y].y - a[x].y) + a[x].x + a[y].x;
}
ll ans = -1e18;
void dg(int x, int y, int l, int r) {
if(x > y) return;
if(x == y) {
fo(i, l, r) if(x + m - 1 <= i)
ans = max(ans, query(x, i));
return;
}
int mi = x + y >> 1;
int st = max(l, mi + m - 1);
if(st > r) {
dg(x, mi - 1, l, r);
return;
}
int u = st; ll v = query(mi, u);
fo(i, st + 1, r) {
ll v2 = query(mi, i);
if(v2 > v) u = i, v = v2;
}
ans = max(ans, v);
dg(x, mi - 1, l, u);
dg(mi + 1, y, u, r);
}
int main() {
freopen("cake3.in", "r", stdin);
freopen("cake3.out", "w", stdout);
scanf("%d %d", &n, &m);
fo(i, 1, n) scanf("%lld %lld", &a[i].x, &a[i].y);
sort(a + 1, a + n + 1, cmp);
fo(i, 1, n) b[i] = i;
sort(b + 1, b + n + 1, cmp2);
fo(i, 1, n) tb[b[i]] = i;
fo(i, 1, n) {
g[i] = g[i - 1];
pl = pr = tb[i];
add(g[i], 1, n);
}
dg(1, n, 1, n);
pp("%lld\n", ans);
}