首页 > 其他分享 >李超线段树模板

李超线段树模板

时间:2023-07-07 12:13:57浏览次数:39  
标签:return int 线段 李超 st xx line fz 模板

细节和理解详见注释
题目: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);
		}
	}
}

标签:return,int,线段,李超,st,xx,line,fz,模板
From: https://www.cnblogs.com/linghusama/p/17534588.html

相关文章

  • 微信模板消息推送封装方法
    /***@explain*发送消息通知*@returnarray|mixed*@remark*获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token*access_token每日获取次数是有限制的,access_token有时间限制,可以存储到数据库7200s.7200s后access......
  • wpf样式模板的使用
    <Windowx:Class="WpfApp1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:x="http://schemas.micro......
  • WordPress主题,当前页面使用了哪个template模板文件?
    对于页面与模板的对应情况一般都是能确定的,不过新朋友一时不熟悉可能还是需要花一点时间。其实,可以有一个小技巧,可以快速确定当前页面对应的模板文件。想要实现上面的效果,只需将下面代码加入主题的 functions.php 文件。functionzhuige_admin_bar_init(){//Ifnota......
  • 【线段树】 POJ 3667 Hotel
    这道题和那道HDOJ3308LCIS比较像。。那道题目我就写了超久,当时是不确定保存什么信息。。这道题也写了很久,主要是各种低级错误,找错找了很久,超级火。。。。#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<queue>#include<stack>#inc......
  • 【线段树】 HDOJ 4027 Can you answer these queries?
    想了好久的线段树,用到的思想好巧妙,因为最大是2的63次方,所以开了个6,7次的平方就全变成一了。。。。比较好写的一种方法是直接用不加lazy的线段树更新区间,然后加一个当sum=R-L+1就不更新的剪枝。。。。我的代码是每加一次开根就pushdown,达到7次以后就不更新了。。。#include<iost......
  • 【线段树】 HDOJ 3308 LCIS
    要保存很多信息的线段树,我写的线段树保存了超多的信息,而且pushup写了两遍。。。。有一种比较简单的方法是直接放弃结构体,用数组保存区间的一个端点和区间长度,因为区间长度需要用到很多次,如果选择保存区间的两个端点,那么代码会写的很长很难受。。。。我就是用结构题写的,保存的是区间......
  • 李超线段树
    引入与概括思考下列问题:在平面直角坐标系中维护集合,支持下列操作:加入一个定义域为\([l,r]\)的一次函数。查询所有定义域包含\(x\)的一次函数的函数值的最值。我们发现,这可以看成一个区间修改,单点查询的问题,考虑使用线段树维护。但我们发现传统线段树难以维护,于是......
  • 【线段树】 HDOJ 5274 Dylans loves tree
    用dfs序构建线段树,然后用lca求出两点间路径的xor和。。。#include<iostream>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<cstdio>#include<algorithm>#include<cstring>#include......
  • 线段树分治 学习笔记
    离线算法。在时间轴上建线段树(可能要事先离散化),要维护的东西用vector什么的挂在线段树的节点上,DFS一遍线段树,每次进入一个节点就加入要维护的东西,离开时撤销即可。由于DFS的特性,只需支持最近的undo,用stack可维护。......
  • 代码模板
    代码#defineLLlonglong#defineUNunsigned#include<bits/stdc++.h>usingnamespacestd;//--------------------////--------------------//intmain(){ return0;}快读inlineintrd(){ intret=0,f=1;charch=getchar(); while(ch<'0&#......