[APIO2018] New Home

题面在这里

description

在一个数轴上:
给定(n)个商店,每个商店有一个开业时间,关门时间,坐标和销售物品的种类
同时有(m)个询问,每个询问给你一个时间(t[i])和地点(d[i])试求在(t[i])时刻,一个住在(d[i])的人,为了买某种商品最远需要跑多长距离。

data range

[n,mle 3 imes 10^5,数轴长度le 10^9 ]

solution

(Luogu)评测机好评,我这种大力(Splay)都跑得过

把每一家商店存在的区间看成一组在数轴上的插入,删除操作,使用(Splay)记录每家商店前一家该种类型商店的位置(pre),用(set)记一下就可以了

询问的时候二分距离(len)问题即检查是否有一种商店不在([d[i]-len,d[i]+len])内,
即求(min_{(d[i]+len,infty)}pre),于是记录一个最小值就可以了

艰苦战斗

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
//#define TEST
#define FILE ""
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=1000010;
const int inf=1e9+7;
const dd pi=acos(-1);
il ll read(){
	RG ll data=0,w=1;RG char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
	return data*w;
}

il void file(){
	freopen(FILE"102","r",stdin);
	freopen(FILE"a.out","w",stdout);
}

int n,k,q,m,ans[N];
int x[N],t[N],a[N],b[N],l[N],y[N];
struct operators{
	int opt;//0表示插入一个商店,1表示询问,2表示删除一个商店
	int pos,tim,kind;
}Q[N];
bool cmp(operators a,operators b){
	if(a.tim==b.tim)return a.opt<b.opt;
	else return a.tim<b.tim;
}

il void init(){
	n=read();k=read();q=read();
	for(RG int i=1;i<=n;i++){
		x[i]=read();t[i]=read();a[i]=read();b[i]=read();
		Q[++m]=(operators){0,x[i],a[i],t[i]};
		Q[++m]=(operators){2,x[i],b[i],t[i]};
	}
	for(RG int i=1;i<=q;i++){
		l[i]=read();y[i]=read();
		Q[++m]=(operators){1,l[i],y[i],i};
	}
	sort(Q+1,Q+m+1,cmp);
}

struct store{int pos,id;};
bool operator <(store a,store b){return a.pos<b.pos;}
multiset<store>S[N];
multiset<store>::iterator tmp;

int tot,rt;
int fa[N],s[2][N],pre[N],minpre[N],pos[N];
#define isr(i) (s[1][fa[i]]==i)
il void update(RG int i){
	minpre[i]=pre[i];
	if(pre[s[0][i]]&&pos[minpre[i]]>pos[minpre[s[0][i]]])
		minpre[i]=minpre[s[0][i]];
	if(pre[s[1][i]]&&pos[minpre[i]]>pos[minpre[s[1][i]]])
		minpre[i]=minpre[s[1][i]];
}
il void rot(RG int i){
	RG int j=fa[i],k=fa[j];
	RG bool b=isr(i);
	if(k)s[isr(j)][k]=i;fa[i]=k;
	if(s[!b][i])fa[s[!b][i]]=j;s[b][j]=s[!b][i];
	fa[j]=i;s[!b][i]=j;
	update(j);
}
il void splay(int i,int a){
	for(RG int j=fa[i];j!=a;rot(i),j=fa[i])
		if(fa[j]!=a)isr(i)^isr(j)?rot(i):rot(j);
	if(!a)rt=i;update(i);
}

il void insert(int p){
	RG int i=rt,ff=0;
	while(i){ff=i;i=s[p>pos[i]][i];}
	if(!i)i=++tot;if(!ff)rt=i;
	else s[p>pos[ff]][ff]=i;
	if(ff)fa[i]=ff;pos[i]=p;
	splay(i,0);
}

il void find(int p){
	RG int i=rt;
	while(s[p>pos[i]][i])
		i=s[p>pos[i]][i];
	splay(i,0);
}

il int Nxt(int p,bool b){
	find(p);RG int i=rt;
	if(pos[i]>p&&b)return rt;
	if(pos[i]<p&&!b)return rt;
	i=s[b][rt];while(s[!b][i])i=s[!b][i];return i;
}

il void Delete(int i){
	splay(i,0);
	RG int nxt=s[0][i],lst=s[1][i];
	while(s[1][nxt])nxt=s[1][nxt];
	while(s[0][lst])lst=s[0][lst];
 
	splay(nxt,0);splay(lst,nxt);
	fa[i]=s[0][lst]=0;
	update(lst);update(nxt);
}

il int query(int l){
	RG int L=Nxt(l,0);splay(L,0);
	return pos[minpre[s[1][L]]];
}

il void Ins(int pos,int kind){
	insert(pos);splay(tot,0);
	tmp=S[kind].upper_bound((store){pos,0});
	minpre[tot]=pre[tot]=pre[tmp->id];
	minpre[tmp->id]=pre[tmp->id]=tot;
	splay(tot,0);splay(tmp->id,0);
	S[kind].insert((store){pos,tot});
}
il void Del(int pos,int kind){
	tmp=S[kind].upper_bound((store){pos,0});
	pre[tmp->id]=pre[pre[tmp->id]];splay(tmp->id,0);
	tmp--;Delete(tmp->id);
	S[kind].erase(tmp);
}
il int Qry(int pos){	
	RG int l=0,r=100000000,mid,ret=-1;
	while(l<=r){
		mid=(l+r)>>1;
		if(query(pos+mid+1)>=pos-mid)
			ret=mid,r=mid-1;
		else l=mid+1;
	}
	return ret;
}

int main()
{
	init();pos[0]=-inf;	
	for(RG int i=1;i<=k;i++){
		insert(-inf);update(tot);S[i].insert((store){-inf,tot});
		insert(inf);S[i].insert((store){inf,tot});
		minpre[tot]=pre[tot]=tot-1;update(tot);
	}		
	for(RG int i=1;i<=m;i++){
		if(Q[i].opt==0)Ins(Q[i].pos,Q[i].kind);
		if(Q[i].opt==1)ans[Q[i].kind]=Qry(Q[i].pos);
		if(Q[i].opt==2)Del(Q[i].pos,Q[i].kind);
	}
	for(RG int i=1;i<=q;i++)printf("%d
",ans[i]);
	return 0;
}

原文地址:https://www.cnblogs.com/cjfdf/p/9100520.html