6.22模擬 T1 小蛋糕(分治做決策單調性)

題目大意:


在這裏插入圖片描述

3<=m<=n<=1e5

題解:


顯然是C由小到大是最優的,那麼這時代價就是(最大-最小)*2
先把把所有蛋糕按c排序。

不然發現隨着左端點的遞增,最優決策的右端點是非遞減的。

然後這個東西居然可以分治???(套路太淺)

dg(x,y,l,r)dg(x,y,l,r)表示現在要搞左端點在[x,y][x,y]裏的,它們可能的最優決策區間是[l,r][l,r]

m=(x+y)/2m=(x+y)/2,m的最優決策點是u,這個可以通過暴力掃描[l,r][l,r]得到。

那麼dg(x,m1,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)的,那麼這個做法的複雜度是On log nO(n~log~n)的。

可以這麼分析,每一層的query次數最多是O(n+)=O(n)O(n+段數)=O(n)的,一共有O(log n)O(log~n)

query可以通過預處理一個主席樹來線段樹二分前V前m2m-2大的和來做

總複雜度是O(n log2 n)O(n~log^2~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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章