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
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
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 }