Description
Input
第一行 :一个整数
N
,表示方案和询问的总数。
接下来
若单词为Query,则后接一个整数
T
,表示Blue Mary询问第T天的最大收益。
若单词为Project,则后接两个实数
提示:本题读写数据量可能相当巨大,请选手注意选择高效的文件读写方式。
Output
对于每一个Query,输出一个整数,表示询问的答案,并精确到整百元(以百元为单位,
例如:该天最大收益为
210
或
290
时,均应该输出
2
)。没有方案时回答询问要输出
Sample Input
10
Project 5.10200 0.65000
Project 2.76200 1.43000
Query 4
Query 2
Project 3.80200 1.17000
Query 2
Query 3
Query 1
Project 4.58200 0.91000
Project 5.36200 0.39000
Sample Output
0
0
0
0
0
HINT
Source
思路
线段树标记永久化。见我的博客[Heoi2013]Segment。
代码
#include <cstdio>
const int maxn=100000;
const int maxx=50000;
struct line
{
double k,b;
double f(int x)
{
return k*x+b;
}
};
struct segment_tree
{
int val[(maxx<<2)+10],totl;
double topv;
line li[maxn+10];
int insert(int now,int left,int right,int insv)
{
if(left>right)
{
return 0;
}
int uol=li[insv].f(left)>li[val[now]].f(left);
int uor=li[insv].f(right)>li[val[now]].f(right);
int mid=(left+right)>>1;
if((!val[now])||(uol&&uor))
{
val[now]=insv;
}
else if(uol^uor)
{
double c=(li[insv].b-li[val[now]].b)/(li[val[now]].k-li[insv].k);
if((c<=mid)&&uol)
{
insert(now<<1,left,mid,insv);
}
else if((c<=mid)&&uor)
{
insert(now<<1,left,mid,val[now]);
val[now]=insv;
}
else if((c>mid)&&uol)
{
insert(now<<1|1,mid+1,right,val[now]);
val[now]=insv;
}
else if((c>mid)&&uor)
{
insert(now<<1|1,mid+1,right,insv);
}
}
return 0;
}
inline int ins(double a,double b)
{
++totl;
li[totl].k=b;
li[totl].b=a-b;
insert(1,1,maxx,totl);
return 0;
}
int query(int now,int left,int right,int pos)
{
double ff=li[val[now]].f(pos);
if(ff>topv)
{
topv=ff;
}
if(left==right)
{
return 0;
}
int mid=(left+right)>>1;
if(pos<=mid)
{
query(now<<1,left,mid,pos);
}
if(pos>mid)
{
query(now<<1|1,mid+1,right,pos);
}
return 0;
}
inline int ask(int p)
{
topv=0;
query(1,1,maxx,p);
int ans=topv/100;
return ans;
}
};
segment_tree st;
int n;
char s[10];
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%s",s);
if(s[0]=='P')
{
double a,b;
scanf("%lf%lf",&a,&b);
st.ins(a,b);
}
else
{
int a;
scanf("%d",&a);
printf("%d\n",st.ask(a));
}
}
return 0;
}