JZOJ 7339.改试卷

\(\text{Solution}\)

又忘了线段树分治!!
显然维护一个上凸包
发现加点和删点可以变成限制存在时间
然后把点放在线段树上,线段树下标表示时间
加点时先把点按横坐标排序,然后就可以单调队列维护每个线段树节点的上凸包
询问再按斜率排序,这样可以弹点而不需要二分了
\(O(n \log n)\)

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define re register
#define ls (p << 1)
#define rs (ls | 1)
using namespace std;
typedef long long LL;

const int N = 1e6 + 5;
const LL INF = 0x3f3f3f3f3f3f3f3f;
int n, totp, totq, bz[N];
LL ans[N];

struct point{int x, y, st, ed;}P[N];
struct que{int a, b, ti, id;}Q[N];
inline bool cmpx(point u, point v){return u.x < v.x ? 1 : (u.x == v.x ? u.y > v.y : 0);}
inline bool cmp(que u, que v){return -1.0 * u.a / u.b < -1.0 * v.a / v.b;}
inline double slope(int u, int v)
{
	if (P[u].x == P[v].x) return -INF;
	return 1.0 * (P[u].y - P[v].y) / (P[u].x - P[v].x);
}

inline void read(int &x)
{
	x = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar());
	for(; isdigit(ch); x = (x<<3) + (x<<1) + (ch^48), ch = getchar());
}

vector<int> T[N * 4];
void update(int p, int l, int r, int tl, int tr, int x)
{
	if (tl <= l && r <= tr)
	{
		int sz = T[p].size();
		while (sz > 1 && slope(T[p][sz - 1], T[p][sz - 2]) < slope(T[p][sz - 1], x))
			T[p].pop_back(), sz = T[p].size();
		T[p].push_back(x);
		return;
	}
	int mid = (l + r) >> 1;
	if (tl <= mid) update(ls, l, mid, tl, tr, x);
	if (tr > mid) update(rs, mid + 1, r, tl, tr, x);
}
LL query(int p, int l, int r, int x)
{
	LL res = 0;
	int sz = T[p].size();
	while (sz > 1 && slope(T[p][sz - 1], T[p][sz - 2]) < -1.0 * Q[x].a / Q[x].b)
		T[p].pop_back(), sz = T[p].size();
	if (sz) res = 1LL * Q[x].a * P[T[p][sz - 1]].x + 1LL * Q[x].b * P[T[p][sz - 1]].y;
	if (l == r) return res;
	int mid = (l + r) >> 1;
	if (Q[x].ti <= mid) return max(res, query(ls, l, mid, x));
	return max(res, query(rs, mid + 1, r, x));
}

int main()
{
	freopen("paper.in", "r", stdin), freopen("paper.out", "w", stdout);
	read(n);
	for(re int i = 1, ty; i <= n; i++)
	{
		read(ty);
		if (ty == 3) ++totq, read(Q[totq].a), read(Q[totq].b), Q[totq].ti = i, Q[totq].id = totq;
		else if (ty == 1)
			bz[i] = ++totp, read(P[totp].x), read(P[totp].y), P[totp].st = i, P[totp].ed = n;
		else read(ty), P[bz[ty]].ed = i;
	}
	sort(P + 1, P + totp + 1, cmpx), sort(Q + 1, Q + totq + 1, cmp);
	for(re int i = 1; i <= totp; i++) update(1, 1, n, P[i].st, P[i].ed, i);
	for(re int i = 1; i <= totq; i++) 
	if (!Q[i].ti) ans[Q[i].id] = 0; else ans[Q[i].id] = query(1, 1, n, i);
	for(re int i = 1; i <= totq; i++) printf("%lld\n", ans[i]);
}
posted @ 2021-11-05 13:48  leiyuanze  阅读(26)  评论(0编辑  收藏  举报