您的位置:首页 > 产品设计 > UI/UE

[JSOI2008]Blue Mary开公司(李超线段树)

2018-03-09 20:50 267 查看

题目描述:

有两个操作

Project b k 表示 第一天有 b 的收益 以后每天增加 k 的收益

Query x 表示 查询 第 x 天的最大收益是多少

题目分析:

对于每个计划 第X天的收益可以表示为 P(i)=k*(i-1)+b

形式为一个一次函数

题目可表示为维护每个点上覆盖本点1次函数的最大值是多少

如何维护一条线段上的一次函数?

用超哥线段树啊(雾





题目链接:

Luogu 4254

BZOJ 1568

Ac 代码:

#include <cstdio>
#include <iostream>
const int maxm=500003;
double b[maxm*2],k[maxm*2];
int st[maxm*4],cnt;
inline bool pd(int x,int y,int pos) {return b[x]+(pos-1)*k[x]>b[y]+(pos-1)*k[y];}
inline double getans(int x,int pos) {return b[x]+(pos-1)*k[x];}
double d[]={0,1e-1,1e-2,1e-3,1e-4,1e-5,1e-6,1e-7,1e-8,1e-9,1e-10};
double read()
{
int x=0,w=1,now=0,f=0;
double xs=0;
char ch=0;
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'||(ch=='.'))
{
if(ch=='.')
{
f=1;
ch=getchar();
continue;
}
if(f) xs+=(((ch-'0')*d[++now]));
else x=((x<<3)+(x<<1)+ch-'0');
ch=getchar();
}
xs+=(double)x;
return xs*w;
}
void insert(int o,int l,int r,int now)
{
//printf("%d %d %d\n",o,l,r);
if(l>=r)
{
if(pd(now,st[o],l)) st[o]=now;
return;
}
int mid=(l+r)>>1;
if(k[now]>k[st[o]])
{
if(pd(now,st[o],mid))
insert((o<<1),l,mid,st[o]),st[o]=now;
else insert((o<<1)|1,mid+1,r,now);
}
if(k[now]<k[st[o]])
{
if(pd(now,st[o],mid))
insert((o<<1)|1,mid+1,r,st[o]),st[o]=now;
else insert((o<<1),l,mid,now);
}
}
double ask(int o,int l,int r,int ind)
{
if(l>=r) return getans(st[o],ind);
int mid=(l+r)>>1;
double ans=getans(st[o],ind);
if(ind<=mid) return std::max(ans,ask((o<<1),l,mid,ind));
else return std::max(ans,ask((o<<1)|1,mid+1,r,ind));
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char s[20];
scanf("%s",s);
if(s[0]=='P')
{
cnt++;
b[cnt]=read(),k[cnt]=read();
insert(1,1,maxm,cnt);
}
else
{
int d;
scanf("%d",&d);
printf("%d\n",(int)ask(1,1,maxm,d)/100);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: