李超線段樹實際就是線段樹(廢話)
每一個節點維護一個永久化的標記(這裏只是必定程度上的永久化但仍是要下傳的)
讓線段樹中的一個節點只對應一條直線,那麼若是在這個區間加入一條直線怎麼辦呢?要分類討論,設新加入的f1(x)=k1x+b1,原來的f2(x)=k2x+b2,左端點爲l,右端點爲r,那麼有:
1.f1(d[l])<f2(d[l])且f1(d[r])<f2(d[r]),對應一條直線在兩個端點都比另外一條小,那麼顯然在l~r中f1(x)到處比f2(x)小,直接把f2(x)替換爲f1(x);
2.同理若上式的兩個符號都爲>,那麼f1(x)到處不如f2(x)優,不作更改。
3.k1<k2,那麼因爲不知足1.2,顯然兩條直線有交點,此時解不等式f1(x)<f2(x)獲得x>(b1-b2)/(k2-k1),那麼判斷(b1-b2)/(k2-k1)在左半區間仍是右半區間遞歸下傳便可;
4.k1>k2同理。
時間複雜度爲\(O(n\log^2n)\)
這實際就是模板題(把每種方案轉化成線段)
#include <bits/stdc++.h>
#define N 50005
#define db double
using namespace std;
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline db Max(register db a,register db b)
{
return a>b?a:b;
}
int n,m;
struct node{
db k,b;
int id;
inline db getv(register int x)
{
return k*x+b;
}
};
inline bool cmp(register node a,register node b,register int x)
{
if(!a.id)
return 1;
return a.getv(x)!=b.getv(x)?a.getv(x)<b.getv(x):a.id<b.id;
}
node tr[N<<2];
inline void insert(register int x,register int l,register int r,register node v)
{
if(!tr[x].id)
tr[x]=v;
if(cmp(tr[x],v,l))
swap(tr[x],v);
if(l==r||tr[x].k==v.k)
return;
int mid=l+r>>1;
db X=(tr[x].b-v.b)/(v.k-tr[x].k);
if(X<l||X>r)
return;
if(X<=mid)
insert(x<<1,l,mid,tr[x]),tr[x]=v;
else
insert(x<<1|1,mid+1,r,v);
}
inline void Insert(register int x,register int l,register int r,register int L,register int R,register node v)
{
if(L<=l&&r<=R)
{
insert(x,l,r,v);
return;
}
int mid=l+r>>1;
if(L<=mid)
Insert(x<<1,l,mid,L,R,v);
if(R>mid)
Insert(x<<1|1,mid+1,r,L,R,v);
}
inline node query(register int x,register int l,register int r,register int pos)
{
if(l==r)
return tr[x];
int mid=l+r>>1;
node tmp;
if(pos<=mid)
tmp=query(x<<1,l,mid,pos);
else
tmp=query(x<<1|1,mid+1,r,pos);
return cmp(tr[x],tmp,pos)?tmp:tr[x];
}
int main()
{
m=read(),n=50000;
char opt[15];
while(m--)
{
scanf("%s",opt);
if(opt[0]=='P')
{
db k,b;
scanf("%lf%lf",&k,&b);
node tmp;
tmp.k=b,tmp.b=k-b,tmp.id=1;
Insert(1,1,n,1,n,tmp);
}
else
{
int x=read();
printf("%lld\n",(long long)(query(1,1,n,x).getv(x)/100+1e-8));
}
}
return 0;
}
相關習題