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