最后冲刺!!!|

铃狐sama

园龄:1年11个月粉丝:5关注:5

李超线段树模板

细节和理解详见注释
题目:https://www.luogu.com.cn/problem/P4097

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod1=39989;
const int mod2=1e9;
const double eps=1e-9;
typedef pair <double,int> pdi;
int lasans;
//细节:
//注意42排,开始时s全是0,所以可以特判下(我的编号没有=0的)
// 还有x=xx的特判也很烦wa on 7 ,所以补了return 
//还是错,详细见35,37 
struct node{
	double fz;
	double fm;//fz除以fm=k
	double b;
}line[1600005];
int s[1600005];//存储当前i根下的最佳答案 
int biggerk(node x,node y){
	if(x.fz*y.fm>y.fz*x.fm){
		return 1;
	}
	else if(x.fz*y.fm==y.fz*x.fm){
		return 0;
	}
	else{
		return -1;
	}
}
int st;
void add(int x,int y,int xx,int yy){
	st++;
	if(x==xx){
		line[st].fz=0;
		line[st].fm=1;//最开始这里也没写,没有写的话一开始0,会导致除法错误 
		line[st].b=max(y,yy);
		return;//这里原来没写,wa on 7 
	}
	line[st].fz=yy-y;
	line[st].fm=xx-x;
	line[st].b=((double)y-(double)((line[st].fz*x)/line[st].fm));
}
double calc(int id,int d){//在坐标d下的y值计算 
	if(id==0){
		return 0;
	}
	return line[id].b+(line[id].fz*d)/line[id].fm;
}
int cmp(double x,double y){
	if(x-y>eps){
		return 1;
	}
	else if(y-x>eps){
		return -1;
	}
	else{
		return 0;
	}
}
void upd(int rt,int cl,int cr,int u){
	int &v=s[rt];//看中间原来最高的 
	int mid=(cl+cr)/2;
	if(calc(u,mid)>calc(v,mid)){//中点在上 
		swap(u,v);
	}
	//现在u是较小点,v是较大点(指中间点y坐标 ) 
	int bl=cmp(calc(u,cl),calc(v,cl));//看左侧哪个高 
	int br=cmp(calc(u,cr),calc(v,cr));//看右侧哪个高 
	if(bl==1||(!bl&&u<v)){//中间较小点在右侧却更高 
		upd(rt*2,cl,mid,u);//左侧应该是要更改的 
		//但此时右边不需要再更改了,右边s定为v 
	}
	if(br==1||(!br&&u<v)){
		upd(rt*2+1,mid+1,cr,u);//同理,修改右边的 
	}
	
}
void updata(int rt,int cl,int cr,int l,int r,int u){
	//用于寻找完全覆盖区间 
	if(l<=cl&&cr<=r){//区间被完全覆盖 
		upd(rt,cl,cr,u);
		return;
	}
	int mid=(cl+cr)/2;
	if(l<=mid){
		updata(rt*2,cl,mid,l,r,u);
	}
	if(mid<r){
		updata(rt*2+1,mid+1,cr,l,r,u);
	}
}
pdi pmax(pdi x, pdi y) {  // pair max函数
  if (cmp(x.first, y.first)==-1)//前者小 
    return y;
  else if (cmp(x.first, y.first) == 1)//后者小 
    return x;
  else
    return x.second < y.second ? x : y;//无法判断(eps精度问题) 
}
pdi find(int rt,int l,int r,int d){
	if(d>r||d<l){
		return{0,0};
	}
	int mid=(l+r)/2;
	double res=calc(s[rt],d);//此区间内最佳线段的y值
	if(l==r){
		return {res,s[rt]};//一个点的时候,就是答案 
	} 
	return pmax((pdi){res,s[rt]}, pmax(find(rt*2,l,mid,d),find(rt*2+1,mid +1,r,d)));//否则的话,就是所有包含x的区间的答案最大值 
}
signed main(){
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	while(n--){
		int op;
		cin >> op;
		if(op==0){
			int x;
			cin >> x;
			x=(x+lasans-1)%mod1+1;
			lasans=find(1,1,mod1,x).second;
			cout<<lasans<<endl; 
//			for(int i=1;i<=8;i++){
//				cout<<s[i];
//			}
		}
		else if(op==1){
			int x,y,xx,yy;
			cin >> x >> y >> xx >> yy;
			x=(x+lasans-1)%mod1+1;
			xx=(xx+lasans-1)%mod1+1;
			y=(y+lasans-1)%mod2+1;
			yy=(yy+lasans-1)%mod2+1;
			if(x>xx){
				swap(x,xx);
				swap(y,yy);
			}
			add(x,y,xx,yy);
			updata(1,1,mod1,x,xx,st);
		}
	}
}

本文作者:linghusama

本文链接:https://www.cnblogs.com/linghusama/p/17534588.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   铃狐sama  阅读(8)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示