QOJ 2266. Colorful Rectangle
QOJ 2266. Colorful Rectangle/SS250220A
题意
给定 \(n\) 个点,每个点有颜色 \(\in \{0,1,2\}\)。
求最小周长的矩形,使得矩形内部包含三种颜色的点。
\(n \le 10^5\)。
思路
考场想的分治做法。不会维护信息,所以获得 \(0 pts\)。
题解是偏序问题做法,我怎么没想偏序呢?

点的关系一共就这三种,从左到右标颜色 \(0,1,2\),其他情况都是旋转以及改变颜色排列得到的。
需要单 \(\log\) 的巨大常数做法。
考虑他们要满足什么偏序关系:
- \(x_0 < x_1 < x_2 \land y_1 < y_2 < y_0\)
- \(x_0 \le x_1 \le x_2 \land y_0 \le y_1 \le y_2\)
因为是求最小值,所以你也可以认为所有 \(<\) 都是 \(\le\)。
第二种是好做的。
拆成两个不相干的二维偏序:\(x_0<x_1\land y_0<y_1,x_1<x_2\land y_1<y_2\)。扫描 \(x\) 这一维做,时间复杂度 \(O(n \log n)\)。
做第一种的话,求的东西不可差分。有 \(3\) 种颜色,考虑把其中两个颜色看做数据,第三种颜色看做询问。遇到数据时往询问贡献。遇到询问就单点查询。扫描需要先遇到数据再遇到询问。
不能单点修改,区间查询是因为询问如果弄两种颜色,无法在同一个时间访问到一组询问。
第二种情况不能使用一样的做法,是因为无法保证先遍历到数据再遍历询问,而且数据向询问贡献时,数据之间互不影响。
从小到大扫描 \(x\) 这一维。遇到 \(0,1\) 按照 \(2\) 的 \(y\) 为下标修改线段树等数据结构。遇到 \(2\) 就单点查询。
因为 \(0,1\) 除了 \(y\) 的偏序,\(x\) 也需要满足偏序关系,即需要满足 \(0\) 的时间戳在 \(1\) 之前。这个可以在线段树下放标记的时候处理一下下放的顺序。
具体地,线段树维护 \(0\) 的最小 \(-x+y\)(标记 \(0\)),\(1\) 的最小 \(-y\)(标记 \(1\)),以及最小的两个信息的和(标记 \(2\))。线段树任意节点的标记需要保证任意时刻标记 \(0\) 的时间戳小于标记 \(1\) 的,以及所有标记的时间戳均大于子节点标记的时间戳。
实现标记下放的方式是在下放标记 \(0\) 的时候,如果存在子节点标记 \(1\),就先把子节点的标记 \(1\) 放下去。其他没有什么难点了。
可能需要注意一下两点共水平线的情况有没有考虑到。题目保证不存在三个不同色点共水平线。
时间复杂度 \(O(n \log n)\)。
常数超级大。
code
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {
template<typename T>
void _min(T &a,T b) { a=min(a,b); }
constexpr int N=1e5+7,infint=0x7f7f7f7f;
constexpr ll infll=0x3f3f3f3f3f3f3f3f;
int n;
struct node {
int x,y,c;
}a[N];
int b[N],m;
ll ans=infll;
bool cmpx(node a,node b) { return a.x!=b.x? a.x < b.x: a.y<b.y; }
struct mit {
int tr[N];
void clear() { memset(tr,0x7f,sizeof(tr)); }
void add(int x,int val) { for(;x<=m;x+=x&-x) tr[x]=min(tr[x],val); }
int query(int x) {
int s=infint;
for(;x;x-=x&-x) s=min(s,tr[x]);
return s;
}
}T1[3][2];
void solve1() {
rep(i,0,2) rep(j,0,1) T1[i][j].clear();
rep(i,1,n) b[i]=a[i].y;
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
sort(a+1,a+n+1,cmpx);
rep(i,1,n) {
int x=a[i].x, y=a[i].y, c=a[i].c, _y=lower_bound(b+1,b+m+1,y)-b;
int ne=(c+1)%3;
int val=T1[c][0].query(_y);
ans=min(ans,(1ll*T1[c][1].query(_y)+x+y)<<1ll);
T1[ne][0].add(_y,-x-y);
T1[ne][1].add(_y,val);
}
}
struct seg {
ll tag[N<<2][3];
void clear() {
memset(tag,0x3f,sizeof(tag));
}
void maketag(int u,int l,int r,ll val,int op) {
if(op==1) _min(tag[u][1],val), _min(tag[u][2],tag[u][1]+tag[u][0]);
else if(op==0) {
if(l!=r && tag[u][1]!=infll) {
int mid=(l+r)>>1;
maketag(u<<1,l,mid,tag[u][1],1), maketag(u<<1|1,mid+1,r,tag[u][1],1);
}
tag[u][1]=infll;
_min(tag[u][0],val);
} else _min(tag[u][2],val);
}
void pushdown(int u,int l,int r,int mid) {
rep(op,0,2) if(tag[u][op]!=infll) maketag(u<<1,l,mid,tag[u][op],op), maketag(u<<1|1,mid+1,r,tag[u][op],op);
memset(tag[u],0x3f,sizeof(tag[u]));
}
void change(int u,int l,int r,int L,int R,int val,int op) {
if(l>=L && r<=R) return maketag(u,l,r,val,op);
int mid=(l+r)>>1;
pushdown(u,l,r,mid);
if(L<=mid) change(u<<1,l,mid,L,R,val,op);
if(mid+1<=R) change(u<<1|1,mid+1,r,L,R,val,op);
}
ll query(int u,int l,int r,int x) {
if(l==r) return tag[u][2];
int mid=(l+r)>>1;
pushdown(u,l,r,mid);
if(x<=mid) return query(u<<1,l,mid,x);
return query(u<<1|1,mid+1,r,x);
}
}T2;
void solve2() {
rep(i,1,n) b[i]=a[i].y;
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
sort(a+1,a+n+1,cmpx);
int t[3]={0,1,2};
do {
T2.clear();
rep(i,1,n) {
int x=a[i].x, y=a[i].y, c=a[i].c, _y=lower_bound(b+1,b+m+1,y)-b;
if(c==t[0]) T2.change(1,1,m,1,_y,-x+y,0);
else if(c==t[1]) T2.change(1,1,m,_y,m,-y,1);
else ans=min(ans,(T2.query(1,1,m,_y)+x)<<1ll);
}
} while(next_permutation(t,t+3));
}
void main() {
sf("%d",&n);
rep(i,1,n) sf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);
solve1();
solve2();
rep(i,1,n) swap(a[i].x,a[i].y), a[i].y*=-1;
solve1();
solve2();
rep(i,1,n) swap(a[i].x,a[i].y), a[i].y*=-1;
solve1();
solve2();
rep(i,1,n) swap(a[i].x,a[i].y), a[i].y*=-1;
solve1();
solve2();
pf("%lld\n",ans);
}
}
int main() {
#ifdef LOCAL
freopen("my.out","w",stdout);
#else
freopen("square.in","r",stdin);
freopen("square.out","w",stdout);
#endif
wing_heart :: main();
}
本文来自博客园,作者:wing_heart,转载请注明原文链接:https://www.cnblogs.com/wingheart/p/18726657

浙公网安备 33010602011771号