bzoj 1568: [JSOI2008]Blue Mary开公司
1568: [JSOI2008]Blue Mary开公司
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1100 Solved: 386
[Submit][Status][Discuss]
Description
Input
第一行 :一个整数N ,表示方案和询问的总数。
接下来N行,每行开头一个单词“Query”或“Project”。
若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益。
若单词为Project,则后接两个实数S,P,表示该种设计方案第一天的收益S,以及以后每天比上一天多出的收益P。
1 <= N <= 100000 1 <= T <=50000 0 < P < 100,| S | <= 10^6
提示:本题读写数据量可能相当巨大,请选手注意选择高效的文件读写方式。
Output
对于每一个Query,输出一个整数,表示询问的答案,并精确到整百元(以百元为单位,
例如:该天最大收益为210或290时,均应该输出2)。没有方案时回答询问要输出0
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
超哥线段树
线段树的每个结点上存的是这个区间对应的一条线段。
插入时,新线段完全更劣,则不进行修改
新线段完全更优,替换旧线段,向下update,若部分更优,把优的部分多的那条线段留在这个结点,
把另一条线段较优的那部分截出来,更新该节点子树
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; #define N 500004 double a[N*2],b[N*2]; int tree[N*4],n,cnt=0; inline bool check(int i,int j,int k) { return a[i]+b[i]*(k-1)>a[j]+b[j]*(k-1); } inline double calc(int k,int x) { return (a[k]+b[k]*(x-1)); } void modify(int l,int r,int rt,int x) { if(l==r) { if(check(x,tree[rt],l)) tree[rt]=x; return; } int mid=(l+r)>>1; if(b[x]>b[tree[rt]]) { if(check(x,tree[rt],mid)) modify(l,mid,rt<<1,tree[rt]),tree[rt]=x; else modify(mid+1,r,rt<<1|1,x); } if(b[x]<=b[tree[rt]]) { if(check(x,tree[rt],mid))modify(mid+1,r,rt<<1|1,tree[rt]),tree[rt]=x; else modify(l,mid,rt<<1,x); } } double query(int l,int r,int rt,int x) { if(l==r) return calc(tree[rt],x); int mid=(l+r)>>1; double ans = calc(tree[rt],x); if(x<=mid) ans=max(ans,query(l,mid,rt<<1,x)); if(x>mid)ans=max(ans,query(mid+1,r,rt<<1|1,x)); return ans; } int main() { scanf("%d",&n); char s[20]; while(n--) { scanf("%s",s); if(s[0]=='P') { scanf("%lf%lf",&a[cnt],&b[cnt]); modify(1,N,1,cnt); } else { int x; scanf("%d",&x); double tmp=query(1,N,1,x); int ans=tmp/100.00; printf("%d\n",ans); } } return 0; }