Codeforces Round #548 (Div. 2) F splay(新坑) + 思维

https://codeforces.com/contest/1139/problem/F

题意

有m个人,n道菜,每道菜有(p_i),(s_i),(b_i),每个人有(inc_j),(pref_j),一个人可以买一道菜的条件是
1. (p_i leq inc_j leq s_i)
2. (|b_i - pref_j| leq inc_j-p_i)
,问每个人分别能买多少道菜

题解

  • 转化一下公式
    1. (p_i leq inc_j leq s_i)
    • 下面两个满足其一即可
    1. (b_i + p_i leq inc_j + pref_j)
    2. (p_i - b_i leq inc_j - pref_j)
  • 对于每个j只需要找出有多少个i满足要求就行
  • (p_i leq inc_j leq s_i)建立时间节点并排序,然后从前往后扫一遍,用两颗splay维护后两个式子并计数

代码

#include<bits/stdc++.h>
#define ls(x) tr[x].son[0]
#define rs(x) tr[x].son[1]
#define MAXN 200005
using namespace std;
struct SPLAY{
	int root=0,tot=0;
	struct node{
		int son[2],par;
		int sz,tsz,v;
		void init(int _v=0,int _sz=0){
			v=_v;
			tsz=sz=_sz;
			son[0]=son[1]=par=0;
		}
	}tr[MAXN];
	void push_up(int x){
		tr[x].tsz=tr[x].sz+tr[ls(x)].tsz+tr[rs(x)].tsz;
	}
	int chk(int x){
		return rs(tr[x].par)==x;
	}
	void rot(int x){
		int y=tr[x].par,z=tr[y].par,k=chk(x),w=tr[x].son[k^1];
		tr[y].son[k]=w;tr[w].par=y;
		tr[z].son[chk(y)]=x;tr[x].par=z;
		tr[x].son[k^1]=y;tr[y].par=x;
		push_up(y);
		push_up(x);
	}
	void splay(int x,int goal){
		while(tr[x].par!=goal){
			int y=tr[x].par,z=tr[y].par;
			if(z!=goal){
				if(chk(x)==chk(y))rot(y);
				else rot(x);
			}
			rot(x);
		}
		if(!goal)root=x;
	}
	void insert(int v,int sz){
		int p=root,ff=0;
		while(p&&tr[p].v!=v){
			ff=p;
			p=tr[p].son[v>tr[p].v];
		}
		if(p){
			tr[p].sz+=sz;
		}else{
			p=++tot;
			if(ff)tr[ff].son[v>tr[ff].v]=p;
			tr[p].init(v,sz);
			tr[p].par=ff;
		}
		splay(p,0);
	}
	int count(int v){
		insert(v,1);
		int re=tr[rs(root)].tsz;
		insert(v,-1);
		return re;
	}
}V[2];
int n,m,p[MAXN],s[MAXN],b[MAXN],inc[MAXN],pref[MAXN],ans[MAXN];
int cnt=0,tot=0;

struct node{
	int v,id,kd;
}A[MAXN*4];
bool cmp(node x,node y){
	if(x.v==y.v)return x.kd<y.kd;
	return x.v<y.v;
}
void add(int v,int id,int kd){
	A[++tot].v=v;
	A[tot].id=id;
	A[tot].kd=kd;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)scanf("%d",&p[i]),add(p[i],i,1);	
	for(int i=1;i<=n;i++)scanf("%d",&s[i]),add(s[i],i,3);
	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
	for(int i=1;i<=m;i++)scanf("%d",&inc[i]),add(inc[i],i,2);
	for(int i=1;i<=m;i++)scanf("%d",&pref[i]);
	sort(A+1,A+tot+1,cmp);
	for(int i=1;i<=tot;i++){
		int id=A[i].id;
		if(A[i].kd==1){
			cnt++;
			V[0].insert(b[id]+p[id],1);
			V[1].insert(p[id]-b[id],1);	
		}else if(A[i].kd==2){
			ans[id]=cnt-V[0].count(inc[id]+pref[id])-V[1].count(inc[id]-pref[id]);	
		}else{
			cnt--;
			V[0].insert(b[id]+p[id],-1);
			V[1].insert(p[id]-b[id],-1);
		}
	}
	for(int i=1;i<=m;i++)printf("%d ",ans[i]);
}
原文地址:https://www.cnblogs.com/VIrtu0s0/p/10631423.html