luogu P4097 [HEOI2013]Segment
李超线段树模板题。
大概思路呢,就是每个区间留着一个标记\(tag\)表示在这个区间中点函数值最大线段的编号,然后在不停的放线段进去递归处理就行了。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100009,M=40000;
int n,Q;
struct LC_Tree
{
int Max[M*4],cnt;
double K[N],B[N];
double val(int id,int x)
{
return x*K[id]+B[id];
}
void Ins(int x,int y,int X,int Y)
{
cnt++;
K[cnt]=1.*(Y-y)/(X-x);
B[cnt]=Y-K[cnt]*X;
}
void Modify(int k,int l,int r,int id)
{
if(l==r)
{
Max[k]=val(Max[k],l)>val(id,l)?Max[k]:id;
return;
}
int mid=l+r>>1;
if(K[id]>K[Max[k]])
{
if(val(id,mid)>val(Max[k],mid))
Modify(k<<1,l,mid,Max[k]),Max[k]=id;
else
Modify(k<<1|1,mid+1,r,id);
}
else
{
if(val(id,mid)>val(Max[k],mid))
Modify(k<<1|1,mid+1,r,Max[k]),Max[k]=id;
else
Modify(k<<1,l,mid,id);
}
}
void change(int k,int l,int r,int x,int y,int id)
{
if(l>=x&&r<=y)
{
Modify(k,l,r,id);
return;
}
int mid=l+r>>1;
if(mid>=x)
change(k<<1,l,mid,x,y,id);
if(mid<y)
change(k<<1|1,mid+1,r,x,y,id);
}
double Query(int k,int l,int r,int x)
{
if(l==r)
return Max[k];
int mid=l+r>>1,qwq;
double ans=Max[k];
if(mid>=x)
ans=val(qwq=Query(k<<1,l,mid,x),x)>val(ans,x)?qwq:ans;
else
ans=val(qwq=Query(k<<1|1,mid+1,r,x),x)>val(ans,x)?qwq:ans;
return ans;
}
}A;
void init()
{
scanf("%d",&n);
}
void work()
{
int last=0,opt,x,y,X,Y;
for (int _=1;_<=n;_++)
{
scanf("%d",&opt);
if(opt==0)
{
scanf("%d",&x);
x=(x+last-1)%39989+1;
printf("%d\n",last=A.Query(1,1,M,x));
}
else
{
scanf("%d %d %d %d",&x,&y,&X,&Y);
x=(x+last-1)%39989+1,y=(y+last-1)%1000000000+1;
X=(X+last-1)%39989+1,Y=(Y+last-1)%1000000000+1;
if(x>X)
swap(x,X),swap(y,Y);
A.Ins(x,y,X,Y);
A.change(1,1,M,x,X,A.cnt);
}
}
}
int main()
{
init();
work();
return 0;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!