bzoj1568: [JSOI2008]Blue Mary开公司

Description

Input

第一行 :一个整数N ,表示方案和询问的总数。 接下来N行,每行开头一个单词“Query”或“Project”。 若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益。 若单词为Project,则后接两个实数S,P,表示该种设计方案第一天的收益S,以及以后每天比上一天多出的收益P。

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
 
 
 
这个样例弱到不想说什么....
自己YY了个二分+线段树- -于是多了个log
然后神犇说可以李超线段树
---------------------------

题解:超哥线段树。

这道题相当于是插入n条直线y=kx+b 

然后查询某x位置所有直线中的最大值。

我们需要用到标记永久化的思想。每次加入一条直线,先判断直线的斜率和本区间记录的直线的斜率,再判断区间中点哪条直线的答案大,如果是斜率大的直线答案大,因为斜率递增,所以在[mid+1,r]中斜率小的直线不会再产生贡献,那么我们把当前区间的答案更改为斜率大的直线,同时将斜率小的直线向[l,mid]中下方。如果是斜率小的直线的答案大,那么斜率大的直线只可能在[mid+1,r]中产生贡献,那么就把当前区间的答案更改为斜率较小的直线,并把斜率大的直线向[mid+1,r]下方。

查询答案的时候就把经过的区间所记录的直线该点的值都计算一下,取最大值就是答案。

来源:http://blog.csdn.net/clover_hxy/article/details/52503987

---------------------------
 1 #include<bits/stdc++.h>
 2 #define rep(i,l,r) for(int i=l;i<=r;++i)
 3 using namespace std;
 4 typedef double d;
 5 char s[10];
 6 const int N=2023333;
 7 d a[N],b[N],ans;
 8 int n,m,Q,tr[N],x;
 9 bool pd(int x,int y,int now){
10     --now;
11     return a[x]+b[x]*now>a[y]+b[y]*now;
12 }
13 void upd(int x,int l,int r,int now){
14     if(l==r){
15         if(pd(now,tr[x],l)) tr[x]=now;
16         return;
17     }
18     int mid=l+r>>1;
19     if(b[now]>b[tr[x]]){
20         if(pd(now,tr[x],mid)) upd(x<<1,l,mid,tr[x]),tr[x]=now;
21         else upd(x<<1|1,mid+1,r,now);
22     }else {
23         if(pd(now,tr[x],mid)) upd(x<<1|1,mid+1,r,tr[x]),tr[x]=now;
24         else upd(x<<1,l,mid,now);
25     }
26 }
27 void que(int x,int l,int r,int now){
28     ans=max(ans,a[tr[x]]+b[tr[x]]*(now-1));
29     if(l==r)return;
30     int mid=l+r>>1;
31     if(now<=mid)que(x<<1,l,mid,now);else que(x<<1|1,mid+1,r,now);
32 }
33 int main(){
34     cin>>Q; n=500001;
35     while(Q--){
36         scanf("%s",s);
37         if(s[0]=='P'){
38             ++m;
39             scanf("%lf%lf",&a[m],&b[m]);
40             upd(1,1,n,m);            
41         }else {
42             scanf("%d",&x);
43             ans=0;
44             que(1,1,n,x);
45             printf("%d\n",(int)ans/100);
46         }
47     }
48 }
View Code

 

 
posted @ 2017-02-14 14:29  Bloodline  阅读(546)  评论(1编辑  收藏  举报