H-Happy Triangle 动态开点线段树

存个代码

#include 
using namespace std;
int inf=1e9;
const int maxn=2e5+10;
int tr[maxn*36],ls[maxn*36],rs[maxn*36];//存左右儿子节点下标 
int rt;
int cnt=0;
map mp;
void up(int & o,int l,int r,int pos,int v) 
{
	if(!o)//动态开点 
	{
		o=++cnt;//++cnt!
	}
	if(l==r) 
	{
		tr[o] =v;
		return ;
	}
	int mid=(l+r)/2;
	if(pos<=mid) up(ls[o],l,mid,pos,v);
	else up(rs[o],mid+1,r,pos,v);
	int ans=2e9;
	if(ls[o]) ans=min(ans,tr[ls[o]]);
	if(rs[o]) ans=min(ans,tr[rs[o]]);
	tr[o]=ans;
}
int qu(int o,int l,int r,int ql,int qr)
{
	if(ql>qr||!o) return 2e9;
	if(ql<=l&&r<=qr) return tr[o];
	int mid=(l+r)/2;
	int ans=2e9;
	if(ql<=mid) ans=min(ans,qu(ls[o],l,mid,ql,qr));
	if(midsecond==1)//后面存在一个数 且数目为一 
		{
			up(rt,0,inf,it->first,it->first-x);//更新后面数的前驱差 
		}
		it--;
		if(it!=mp.begin())
		{
			it--;
			int v=it->first;
			up(rt,0,inf,x,x-v);//计算前数驱差 
		}
		else 
		{
			up(rt,0,inf,x,2e9);//无前驱  则对答案无贡献 赋值2e9 
		} 
	}
	else if(mp[x]==2)//前驱为自己 前驱差为0 
	{
		up(rt,0,inf,x,0);
	}
		
}

void del(int x)
{
	auto it=mp.lower_bound(x);
	mp[x]--;
	int v=-2e9;
	if(it!=mp.begin())
	{
		it--;
		v=it->first;
		it++;
	}
	if(mp[x]==0)
	{
		it++;
		if(it!=mp.end()&&it->second==1) up(rt,0,inf,it->first,it->first-v);//更新后面那个数的前驱差 
		up(rt,0,inf,x,2e9);//修改自己的前驱差 
		mp.erase(x);//抹去map 
	}
	else if(mp[x]==1) up(rt,0,inf,x,x-v);//更新自己 
	
}
int cul(int x)
{
	auto it=mp.lower_bound(x/2+1);
	if(it==mp.end()) return 2e9;//不存在最小合法数 
	if(it->second>=2) return it->first;// a a x 
	if(it!=mp.begin()) 
	{
		auto l=it;
		l--;
		if(l->first+it->first>x)  return it->first;// b a x
	}
	it++;
	if(it!=mp.end()) return it->first;// a<=b x>b-a
	else return 2e9;	
}
int main()
{
	int q;
	scanf("%d",&q);
	while(q--)
	{
		int n,x;
		scanf("%d%d",&n,&x);
		if(n==1)
		{
			add(x);
		}
		if(n==2)
		{
			del(x);
		}
		if(n==3)
		{
			if(qu(rt,0,inf,cul(x),inf)

 

你可能感兴趣的:(H-Happy Triangle 动态开点线段树)