李超樹詳解


李超樹是個什么東西呢?

其實就是一棵線段樹。。。。

我們來看這一道題

 

其實就是這樣一道題目

在二維空間中插入一條直線,詢問x=k的地方最上面一條直線的編號

李超樹儲存的是區間[l,r]中'最優線段',

最優線段,就是[l,r]中最暴露最長的線段

可以發現在k處的答案就是

所有包含此區間的最優線段中的最優解

代碼也好寫

# include<iostream>
# include<cstdio>
# include<algorithm>
# include<cstring>
# include<cmath>
using namespace std;
const int mn = 50005;
int n,tot,tr[mn*4];
double b[100005],k[100005];
char s[200];
double f(int id,int x)
{
    return k[id]*(x-1)+b[id];
}
void update(int cur,int l,int r,int z)
{
    if(l==r)
    {
        if(f(z,l) > f(tr[cur],l)) tr[cur]=z;
        return ;
    }
    int mid=l+r>>1;
    if(k[tr[cur]] < k[z])
    {
        if(f(z,mid) > f(tr[cur],mid)){
            update(cur<<1,l,mid,tr[cur]);
            tr[cur]=z;
        }
        else update(cur<<1|1,mid+1,r,z);
    }
    if(k[tr[cur]] > k[z])
    {
        if(f(z,mid) > f(tr[cur],mid))
        {
            update(cur<<1|1,mid+1,r,tr[cur]);
            tr[cur]=z;
        }
        else update(cur<<1,l,mid,z);
    }
}
double query(int cur,int l,int r,int x)
{
    if(l==r)
        return f(tr[cur],x);
    int mid=l+r>>1;
    if(mid>=x)
        return max(f(tr[cur],x),query(cur<<1,l,mid,x));
    else return max(f(tr[cur],x),query(cur<<1|1,mid+1,r,x));
}
int main()
{
    int x;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s);
        if(s[0]=='P')
        {
            ++tot;
            scanf("%lf%lf",&b[tot],&k[tot]);
            update(1,1,mn-10,tot);
        }
        else {
            scanf("%d",&x);
            printf("%d\n",int(query(1,1,mn-10,x)/100));
        }
    }
    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM