BZOJ 1568 [JSOI2008]Blue Mary开公司 标记永久化线段树

标记永久化线段树裸题,大体思路如下。

如果当前线段完全低于插入线段,则对插入线段进行标记。
如果当前线段完全高于插入线段,则直接放弃。
其余分情况讨论......
首先求出两条直线交点坐标,将长的线段作为当前节点的标
记,短的线段继续下放。

这里有一个小的注意事项,每天增加K,所以插入时 B 应先减去 K

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=60010;
double tagb[4*maxn],tagk[4*maxn],B,K,ans;
bool flag[maxn*4];
double cross(double k1,double b1,double k2,double b2){return (b2-b1)/(1.0*(k1-k2));}
int n,x,T;
void insert(int rt,int l,int r,double K,double B)
{
    if(!flag[rt]) tagk[rt]=K,tagb[rt]=B,flag[rt]=1;
    else
    {
        int mid=(l+r)>>1;
        double f1=1.0*K*l+B,f2=1.0*tagk[rt]*l+tagb[rt],f3=1.0*K*r+B,f4=1.0*tagk[rt]*r+tagb[rt];
        if(f1<=f2&&f3<=f4) return;
        if(f1>=f2&&f3>=f4) tagk[rt]=K,tagb[rt]=B;
        else
        {
            double xx=cross(K,B,tagk[rt],tagb[rt]);
            if(f1>=f2) 
            {
                if(xx<=mid) insert(rt<<1,l,mid,K,B);
                else insert(rt<<1|1,mid+1,r,tagk[rt],tagb[rt]),tagk[rt]=K,tagb[rt]=B;
            }
            else
            {
                if(mid<xx) insert(rt<<1|1,mid+1,r,K,B);
                else insert(rt<<1,l,mid,tagk[rt],tagb[rt]),tagk[rt]=K,tagb[rt]=B;
            }
        }
    }
}
void query(int rt,int l,int r,int x)
{
    if(flag[rt]) ans=max(ans,1.0*tagk[rt]*x+tagb[rt]);
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) query(rt<<1,l,mid,x);
    else query(rt<<1|1,mid+1,r,x);
}
char op[5];
int main()
{
    int n=50000;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",op);
        if(op[0]=='P')
        {
            scanf("%lf%lf",&B,&K);
            insert(1,1,n,K,B-K);
        }
        else 
        {
            scanf("%d",&x);ans=0;query(1,1,n,x);
            printf("%lld\n",(long long)floor(ans/100.0));
        }
    }
    return 0;   
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值