题解 Paint

传送门

在思维不连贯的时候调题就是浪费时间
我改这题用的时间严格长于改 T3

首先发现就是要找周长最长的内部不含其他点的矩形
枚举最左边界,扫描右边界,set 中维护相邻元素的最大差值可以做到 \(O(n^2\log n)\)
将加点改为删点,右→左扫描右边界+链表可以做到 \(O(n^2)\)

发现一个性质:
最优的矩形一定跨过 \(\frac{w}{2}\)\(\frac{h}{2}\)
证明考虑它蜷缩在一个角上肯定没有选择一个肯定能达到的下界 \(2(\max(w, h)+1)\)
那么利用这个性质
枚举上边界,离散化后线段树上维护出每个下边界 \(i\) 的答案
发现就是 \(y_u-y_i+\min\{t:x_t>\frac{w}{2}\}-\max\{s:x_s\leqslant\frac{w}{2}\}\)
那么这个 \(s, t\) 可以在移动上边界时对左右两边分别维护单调栈
于是转化成了一些区间加减,有亿些细节
复杂度 \(O(n\log n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 300010
#define fir first
#define sec second
#define ll long long
#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int w, h, n;
int x[N], y[N], ans;
pair<int, int> p[N];

namespace force{
	int bin[N], ans;
	void solve() {
		int lim=1<<(n*2), mask=3;
		for (int i=0; i<n; ++i) bin[i]=i<<1;
		for (int s=0; s<lim; ++s) {
			int l=0, r=w, d=0, u=h;
			for (int i=0; i<n; ++i) {
				int tem=(s>>bin[i])&mask;
				if (tem==0) r=min(r, x[i]);
				else if (tem==1) l=max(l, x[i]);
				else if (tem==2) u=min(u, y[i]);
				else d=max(d, y[i]);
			}
			if (l==r || d==u) continue;
			else ans=max(ans, (r-l + u-d)<<1);
		}
		cout<<ans<<endl;
	}
}

namespace task1{
	int ans;
	void solve() {
		x[n]=0; y[n]=1; ++n;
		x[n]=1; y[n]=0; ++n;
		x[n]=w; y[n]=1; ++n;
		x[n]=1; y[n]=h; ++n;
		for (int i=0; i<n; ++i) {
			for (int j=0; j<n; ++j) if (x[j]>x[i]) {
				for (int k=0; k<n; ++k) if (x[k]>x[i] && x[k]<x[j] && y[k]>max(y[i], y[j])) {
					int maxn=-1;
					for (int l=0; l<n; ++l) if (x[l]>x[i] && x[l]<x[j] && y[l]<y[k]) {
						maxn=max(maxn, y[l]);
					}
					if (~maxn) ans=max(ans, (x[j]-x[i] + y[k]-maxn)<<1);
				}
			}
		}
		cout<<ans<<endl;
	}
}

namespace task{
	pair<int, int> lsta[N], rsta[N];
	int uni[N], ltop, rtop, usiz;
	int tl[N<<2], tr[N<<2], val[N<<2], tag[N<<2];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define pushup(p) val[p]=max(val[p<<1], val[p<<1|1])
	void spread(int p) {
		if (!tag[p]) return ;
		val[p<<1]+=tag[p]; tag[p<<1]+=tag[p];
		val[p<<1|1]+=tag[p]; tag[p<<1|1]+=tag[p];
		tag[p]=0;
	}
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r; val[p]=tag[p]=0;
		if (l==r) return ;
		int mid=(tl(p)+tr(p))>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		pushup(p);
	}
	void upd(int p, int l, int r, int dat) {
		if (l<=tl(p)&&r>=tr(p)) {val[p]+=dat; tag[p]+=dat; return ;}
		spread(p);
		int mid=(tl(p)+tr(p))>>1;
		if (l<=mid) upd(p<<1, l, r, dat);
		if (r>mid) upd(p<<1|1, l, r, dat);
		pushup(p);
	}
	// void upd(int p, int l, int r, int dat) {for (int i=l; i<=r; ++i) val[i]+=dat;}
	// int query() {int ans=0; for (int i=0; i<=usiz; ++i) ans=max(ans, val[i]); return ans;}
	void solve() {
		ltop=rtop=usiz=0;
		for (int i=1; i<=n; ++i) uni[++usiz]=p[i].sec;
		sort(uni+1, uni+usiz+1);
		usiz=unique(uni+1, uni+usiz+1)-uni-1; 
		build(1, 0, usiz);
		for (int i=0; i<=usiz; ++i) val[i]=0;
		sort(p+1, p+n+1, [](pair<int, int> a, pair<int, int> b){return a.sec<b.sec;});
		int pos=1;
		// for (int i=1; i<=n; ++i) cout<<"("<<p[i].fir<<','<<p[i].sec<<") "; cout<<endl;
		// cout<<"uni: "; for (int i=1; i<=usiz; ++i) cout<<uni[i]<<' '; cout<<endl;
		for (int i=1; i<=usiz; ++i) {
			// cout<<"i: "<<i<<endl;
			upd(1, 0, i-1, uni[i]-uni[i-1]);
			ans=max(ans, val[1]<<1);
			// cout<<"val: "; for (int j=1; j<=usiz; ++j) cout<<val[j]<<' '; cout<<endl;
			// ans=max(ans, query()<<1);
			// cout<<"lsta: "; for (int j=1; j<=ltop; ++j) cout<<"("<<lsta[j].fir<<','<<lsta[j].sec<<") "; cout<<endl;
			// cout<<"rsta: "; for (int j=1; j<=rtop; ++j) cout<<"("<<rsta[j].fir<<','<<rsta[j].sec<<") "; cout<<endl;
			while (pos<=n && p[pos].sec==uni[i]) {
				if (p[pos].fir<=w/2) {
					int inc=i;
					while (ltop && lsta[ltop].fir<=p[pos].fir) {
						upd(1, lsta[ltop].sec, inc-1, lsta[ltop].fir-p[pos].fir); //, cout<<"decrease: "<<lsta[ltop].fir-p[pos].fir<<endl;
						inc=lsta[ltop--].sec;
					}
					lsta[++ltop]={p[pos].fir, inc};
				}
				else {
					int inc=i;
					while (rtop && rsta[rtop].fir>=p[pos].fir) {
						upd(1, rsta[rtop].sec, inc-1, p[pos].fir-rsta[rtop].fir); //, cout<<"decrease: "<<p[pos].fir-rsta[rtop].fir<<endl;
						inc=rsta[rtop--].sec;
					}
					rsta[++rtop]={p[pos].fir, inc};
				}
				++pos;
			}
			// cout<<"after_lsta: "; for (int j=1; j<=ltop; ++j) cout<<"("<<lsta[j].fir<<','<<lsta[j].sec<<") "; cout<<endl;
			// cout<<"after_rsta: "; for (int j=1; j<=rtop; ++j) cout<<"("<<rsta[j].fir<<','<<rsta[j].sec<<") "; cout<<endl;
			upd(1, i, i, w);
			if (lsta[ltop].fir!=0) lsta[++ltop]={0, i};
			if (rsta[rtop].fir!=w) rsta[++rtop]={w, i};
		}
	}
}

signed main()
{
	freopen("paint.in", "r", stdin);
	freopen("paint.out", "w", stdout);

	w=read(); h=read(); n=read();
	for (int i=1; i<=n; ++i) x[i]=read(), y[i]=read(), p[i]={x[i], y[i]};
	++n; x[n]=w; y[n]=h; p[n]={0, 0};
	++n; x[n]=w; y[n]=h; p[n]={w, h};
	// if (n<=10) force::solve();
	// else task1::solve();
	task::solve();
	swap(w, h);
	for (int i=1; i<=n; ++i) swap(x[i], y[i]), swap(p[i].fir, p[i].sec);
	task::solve();
	cout<<ans<<endl;

	return 0;
}
posted @ 2022-04-03 21:08  Administrator-09  阅读(2)  评论(0编辑  收藏  举报