1568: [JSOI2008]Blue Mary开公司
Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1709 Solved: 595
[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
分析:传说中的标记永久化......
我个人感觉标记永久化就是记录当前区间可能的最优解,便于和从子区间传回的最优解进行比较,看到底谁才是最优解.这道题实际上就是给定若干条直线,求给定横坐标的y值最大的点.利用线段树维护,每个区间记录当前可能的最优解.在区间中点mid处x高于t,说明在区间[L,R]中最优解可能是x,于是在[L,R]上打标机记录直线x.因为两条直线的交点在mid左边,所以左边区间应该打上t的标记(t更有可能成为最优解).就这样不断地修改下去.
查询就是单点查询.返回一条直线,每次将返回的直线与当前区间标记的直线在查询的位置x处比较y值大小,将更优的传上去就好了.
自己理解的标记永久化就是这样了,不能确定最优解时就记录在当前层最有可能的最优解,最后比较返回.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 50010; int q,n = 50000; bool flag = false,vis[maxn << 2]; struct node { double k,b; int id; } e[maxn << 2]; bool cmp(node a,node b,int pos) { double temp1 = (double)a.k * pos + a.b; double temp2 = (double)b.k * pos + b.b; return temp1 < temp2; } double jiao(node a,node b) { return (double)(a.b - b.b) / (b.k - a.k); } void update(int o,int l,int r,int x,int y,node a) { int mid = (l + r) >> 1; if (x <= l && r <= y) { if (!vis[o]) { vis[o] = 1; e[o] = a; } else { double l1 = a.b + (double)a.k * l,l2 = a.b + (double)a.k * r; double r1 = e[o].b + (double)e[o].k * l,r2 = e[o].b + (double)e[o].k * r; if (l1 <= r1 && l2 <= r2) return; if (l1 >= r1 && l2 >= r2) e[o] = a; else { double X = jiao(e[o],a); if (l1 >= r1) { if (X <= mid) update(o * 2,l,mid,x,y,a); else update(o * 2 + 1,mid + 1,r,x,y,e[o]),e[o] = a; } else { if (X > mid) update(o * 2 + 1,mid + 1,r,x,y,a); else update(o * 2,l,mid,x,y,e[o]),e[o] = a; } } } return; } if (x <= mid) update(o * 2,l,mid,x,y,a); if (y > mid) update(o * 2 + 1,mid + 1,r,x,y,a); } node query(int o,int l,int r,int pos) { if (l == r) return e[o]; int mid = (l + r) >> 1; node temp; if (pos <= mid) temp = query(o * 2,l,mid,pos); else temp = query(o * 2 + 1,mid + 1,r,pos); if (cmp(temp,e[o],pos) == 1) return e[o]; else return temp; } int main() { scanf("%d",&q); while (q--) { char ch[10]; double x,y; scanf("%s",ch); if (ch[0] == 'P') { flag = true; scanf("%lf%lf",&x,&y); node temp; temp.k = y; temp.b = x - y; temp.id = 1; update(1,1,n,1,n,temp); } else { int pos; scanf("%d",&pos); if (!flag) puts("0"); else { node temp = query(1,1,n,pos); printf("%lld ",(ll)((temp.k * pos + temp.b) / 100 + 1e-8)); } } } return 0; }