1. 程式人生 > 實用技巧 >Yoi #388.紅點藍點

Yoi #388.紅點藍點

題面


分析

分成四部分,每部分用線段樹維護,由於有刪除操作,所以每個葉子節點用\(multiset\)維護
時間複雜度均攤\(O(nlgn)\)
注意:點權可能是負數,所以$c[0]=-INF

#include<bits/stdc++.h>
const int INF=1e9;
using namespace std;

const int N=1e5+5;
int n,m,d,ans[N],num;
struct A{int a,b,id; }a[N],b[N];

namespace sss {
	bool cmp(A i,A j) {
		return i.b<j.b;
	}
	const int N=3e6+6;
	bool fl;
	struct B{
		int c[N],ls[N],rs[N],cnt,id,num[N]; 
		multiset<int>s[100000];
		void ins(int &p,int l,int r,int x,int k) {
			if(!p) {
				p=++cnt; c[p]=-INF;
			}	
			if(l==r) {
				c[p]=max(c[p],k);
				if(!num[p]) num[p]=++id;
				s[num[p]].insert(k);
				return;
			}
			int mid=l+r>>1;
			if(x<=mid) ins(ls[p],l,mid,x,k);
				else ins (rs[p],mid+1,r,x,k);
			c[p]=max(c[ls[p]],c[rs[p]]);
		}
		void del(int p,int l,int r,int x,int k) {
			if(l==r) {
				auto x=s[num[p]].lower_bound(k);
				s[num[p]].erase(x);
				if(s[num[p]].begin()==s[num[p]].end()) c[p]=-INF;
					else {
						x=s[num[p]].end(); x--;
						c[p]=*x;
					}
				return;
			}
			int mid=l+r>>1;
			if(x<=mid) del(ls[p],l,mid,x,k);
				else del(rs[p],mid+1,r,x,k);
			c[p]=max(c[ls[p]],c[rs[p]]);
		}
		int ask(int p,int l,int r,int x,int y) {
			if(!p) return -INF;
			if(l==x&&r==y) return c[p];
			int mid=l+r>>1;
			if(y<=mid) return ask(ls[p],l,mid,x,y);
			if(x>mid) return ask(rs[p],mid+1,r,x,y);
			return max(ask(ls[p],l,mid,x,mid),ask(rs[p],mid+1,r,mid+1,y));
		}
	/*	bool is_clear(int p,int l,int r) {
			if(!p) return 1;
			if(l==r) {
				if(s[num[p]].begin()==s[num[p]].end()) return 1;
				return 0;
			}
			int mid=l+r>>1;
			return is_clear(ls[p],l,mid)&is_clear(rs[p],mid+1,r);	
		}*/
	}c1,c2;
	void main() {
		int rt=1; c1.cnt=1,c2.cnt=1; c1.c[0]=-INF,c2.c[0]=-INF;
		sort(a+1,a+n+1,cmp);
		sort(b+1,b+n+1,cmp);
		int l=1,r=0;
		for(int i=1;i<=n;i++) ans[i]=INF;
		for(int i=1;i<=n;i++) {
			while(r<=n&&a[i].b>=b[r+1].b) {
				r++;
				c1.ins(rt,0,m,b[r].a,b[r].b+b[r].a);
				c2.ins(rt,0,m,b[r].a,b[r].b-b[r].a);
			}
			while(l<=r&&a[i].b-b[l].b>d) {
				c1.del(rt,0,m,b[l].a,b[l].b+b[l].a);
				c2.del(rt,0,m,b[l].a,b[l].b-b[l].a);
				l++;
			}
			if(l<=r) {
				ans[a[i].id]=min(ans[a[i].id],-c1.ask(rt,0,m,0,a[i].a)+a[i].a+a[i].b);
				ans[a[i].id]=min(ans[a[i].id],-c2.ask(rt,0,m,a[i].a,m)-a[i].a+a[i].b);
			}
		}
		for(int i=l;i<=r;i++) {
			c1.del(rt,0,m,b[i].a,b[i].b+b[i].a);
			c2.del(rt,0,m,b[i].a,b[i].b-b[i].a);
		}
		l=n,r=n+1;
		fl=0;
		for(int i=n;i;i--) {
			while(r>1&&a[i].b<b[r-1].b) {
				r--;
				c1.ins(rt,0,m,b[r].a,-b[r].b+b[r].a);
				c2.ins(rt,0,m,b[r].a,-b[r].b-b[r].a);
			}
			while(l>=r&&b[l].b-a[i].b>d) {
				c1.del(rt,0,m,b[l].a,-b[l].b+b[l].a);
				c2.del(rt,0,m,b[l].a,-b[l].b-b[l].a);
				l--;
			}
			if(l>=r) {
				ans[a[i].id]=min(ans[a[i].id],-c1.ask(rt,0,m,0,a[i].a)+a[i].a-a[i].b);
				ans[a[i].id]=min(ans[a[i].id],-c2.ask(rt,0,m,a[i].a,m)-a[i].a-a[i].b);
			}
		}
		for(int i=1;i<=n;i++) {
			printf("%d\n",ans[i]==INF?0:ans[i]);
		}
	}
}
int main() {
	freopen("portal.in","r",stdin);
	freopen("portal.out","w",stdout);
	scanf("%d%d",&n,&d);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&a[i].a,&a[i].b); a[i].id=i;
	}
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&b[i].a,&b[i].b);
		m=max(m,b[i].a);
	}
	sss::main();
	return 0;
}