【模板】李超线段树 / [HEOI2013] Segment

在一些特殊的题目中,可以使用“标记永久化”代替标记的下传,但应用的局限性很大

  • 在本题中,永久化的标记就是线段树所需要维护的信息,通过沿路比较得到单点查询的答案。在某个区间内,对于两条相交的线段,将其中更可能优的一条录入区间,将另外一条下传到其中一个子区间,就保证了log方的修改时间复杂度
#include <bits/stdc++.h>
using namespace std;
const int mod1=39989,mod2=1000000000;
struct seg
{
	int x0,y0,x1,y1;
	double calc(double x)
	{
		if(x0==x1)
		{
			return y1;
		}
		return y0+(x-x0)/(x1-x0)*(y1-y0);
	}
}s[100005];
int tot;
struct t1
{
	int l,r,v;
}t[200005];
void build(int p,int l,int r)
{
	t[p].l=l;
	t[p].r=r;
	t[p].v=0;
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
const double eps=1e-9;
void change(int p,int l,int r,int x)
{
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=t[p].l&&r>=t[p].r)
	{
		if(fabs(s[x].calc(mid)-s[t[p].v].calc(mid))<eps&&x>t[p].v)
		{
			swap(x,t[p].v);
		}
		else if(s[x].calc(mid)<s[t[p].v].calc(mid))
		{
			swap(x,t[p].v);
		}
		if(fabs(s[x].calc(t[p].r)-s[t[p].v].calc(t[p].r))<eps&&t[p].v<x)
		{
			change(p*2+1,l,r,t[p].v);
			t[p].v=x;
		}
		else if(s[x].calc(t[p].r)<s[t[p].v].calc(t[p].r))
		{
			change(p*2+1,l,r,t[p].v);
			t[p].v=x;
		}
		else if(fabs(s[x].calc(t[p].l)-s[t[p].v].calc(t[p].l))<eps&&t[p].v<x)
		{
			change(p*2,l,r,t[p].v);
			t[p].v=x;
		}
		else if(s[x].calc(t[p].l)<s[t[p].v].calc(t[p].l))
		{
			change(p*2,l,r,t[p].v);
			t[p].v=x;
		}
		else
		{
			t[p].v=x;
		}
		return;
	}
	if(l<=mid)
	{
		change(p*2,l,r,x);
	}
	if(r>mid)
	{
		change(p*2+1,l,r,x);
	}
}
int ask(int p,int x)
{
	if(t[p].l==t[p].r)
	{
		return t[p].v;
	}
	int mid=(t[p].l+t[p].r)>>1,va;
	if(x<=mid)
	{
		va=ask(p*2,x);
	}
	else
	{
		va=ask(p*2+1,x);
	}
	if(fabs(s[t[p].v].calc(x)-s[va].calc(x))<eps)
	{
		return min(t[p].v,va);
	}
	else if(s[t[p].v].calc(x)>s[va].calc(x))
	{
		return t[p].v;
	}
	else
	{
		return va;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin>>n;
	s[0].x0=1;
	s[0].x1=mod1;
	s[0].y0=s[0].y1=0;
	build(1,1,mod1);
	int lastans=0;
	for(int i=1;i<=n;i++)
	{
		int opt;
		cin>>opt;
		if(opt==0)
		{
			int k;
			cin>>k;
			lastans=ask(1,(k+lastans-1)%mod1+1);
			cout<<lastans<<"\n";
		}
		else
		{
			tot++;
			cin>>s[tot].x0>>s[tot].y0>>s[tot].x1>>s[tot].y1;
			s[tot].x0=(s[tot].x0+lastans-1)%mod1+1;
			s[tot].y0=(s[tot].y0+lastans-1)%mod2+1;
			s[tot].x1=(s[tot].x1+lastans-1)%mod1+1;
			s[tot].y1=(s[tot].y1+lastans-1)%mod2+1;
			if(s[tot].x0>s[tot].x1)
			{
				swap(s[tot].x0,s[tot].x1);
				swap(s[tot].y0,s[tot].y1);
			}
			change(1,s[tot].x0,s[tot].x1,tot);
		}
	}
	return 0;
}
posted @ 2025-02-26 15:16  D06  阅读(23)  评论(0)    收藏  举报
//雪花飘落效果