把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu PP4097 [HEOI2013]Segment

题面传送门
李超线段树的板子。
李超线段树是一种利用了标记永久化的线段树。每个区间存储的是这个区间的露在最上面最大的线段。
但是因为是标记永久化所以这个存储的东西本身就是不严格的。
有了这个定义就很好做了。
我们对于每个线段先拆成logn个扔到线段树对应区间,然后再分别插入。
插入的时候根据定义随便讨论即可,注意每次只会一侧递推所以是\(O(log^2n)\)的。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 100000
#define M 500000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,x,y,z,nx,ny,op,Lastans,cnt,tot;db ans,pus;
struct line{db k,b;int id;I db Find(int x){return k*x+b;}}F[N+5<<2];
I void add(line z,int l,int r,int now){
	if(!F[now].id) return (void)(F[now]=z);
	if(F[now].Find(r)<=z.Find(r)&&F[now].Find(l)<=z.Find(l)) return (void)(F[now]=z);
	if(F[now].Find(r)>=z.Find(r)&&F[now].Find(l)>=z.Find(l)) return;int m=l+r>>1;//if(z.id==16) printf("%lf %lf %d %d %d\n",F[now].Find(m),z.Find(m),F[now].id,l,r);
	if(F[now].Find(m)<z.Find(m)){
		if(F[now].Find(l)<z.Find(l)) add(F[now],m+1,r,now<<1|1);else add(F[now],l,m,now<<1);F[now]=z;
	}
	else{
		if(F[now].Find(l)<z.Find(l)) add(z,l,m,now<<1);else add(z,m+1,r,now<<1|1);
	}
}
I void insert(int x,int y,line z,int l=1,int r=mod2,int now=1){
	if(x<=l&&r<=y) return add(z,l,r,now);int m=l+r>>1;x<=m&&(insert(x,y,z,l,m,now<<1),0);y>m&&(insert(x,y,z,m+1,r,now<<1|1),0);
}
I void Query(int x,int l=1,int r=mod2,int now=1){
	db pus=F[now].Find(x);/*printf("%d %d\n",F[now].id,now);*/(pus>ans||((ans==pus)&&tot>F[now].id))&&(ans=pus,tot=F[now].id);if(l==r) return;int m=l+r>>1;
	x<=m?Query(x,l,m,now<<1):Query(x,m+1,r,now<<1|1);
}
I void swap(int &x,int &y){x^=y^=x^=y;}
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i;scanf("%d",&n);while(n--){
		scanf("%d",&op);if(!op) scanf("%d",&x),x=(x+Lastans-1)%mod2+1,ans=tot=-1e9,Query(x),printf("%d\n",Lastans=tot);
		else{ 
			++cnt;scanf("%d%d%d%d",&x,&y,&nx,&ny);x=(x+Lastans-1)%mod2+1;y=(y+Lastans-1)%mod+1;nx=(nx+Lastans-1)%mod2+1;ny=(ny+Lastans-1)%mod+1;//printf("%d %d %d %d\n",x,y,nx,ny);
			x>nx&&(swap(x,nx),swap(y,ny),0);if(x==nx) insert(x,x,(line){0,max(y,ny),cnt});else insert(x,nx,(line){(ny-y)*1.0/(nx-x),y-x*((ny-y)*1.0/(nx-x)),cnt});
		}
	}
}
posted @ 2021-07-14 21:07  275307894a  阅读(59)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end