真正的危机不是机器人像人一样思考,而是人像机器一样思考。 ——凉宫春日的忧郁

[HZOJ10420]计算

[HZOJ10420]计算

题目

给定一个数列,第i个位置包含两个数ai,bi

每次询问给出x,y

求数列ai*x+bi*y的最大值

输入所有数为自然数,在int范围内

INPUT

第一行为n,m。n为数列长度,m为询问个数。

接下来n行,每行两个数,代表ai,bi

接下来m行,每行两个数,代表x,y

OUTPUT

共m行,每行输出一个答案

SAMPLE

INPUT

3 3

1 5

9 0

9 1

4 4

1 1

3 4

OUTPUT

40

10

31

解题报告

首道估值线段树留念

首先,我们看题目,输入所有数据为自然数,自然数意味着不会有负数,那么,我们就可以确定,$a$和$b$越大,答案也就可能越大

剩下的就是如何找到准确的最大值了

我们可以用线段树处理出来每个区间的最大的$a$和$b$,然后,对于每一个询问,我们在线段树中进行搜索,我们可以用这个区间最大的$a$和$b$来限制搜索的范围,具体做法:

对于每一次搜索,我们先瞎XX搜到某一个子节点(一般来说是第一个子节点,根据线段树的实现而定),获得一个准确的$ans$值,然后,我们在搜索的时候,假如获得的该区间最大的$a$和$b$所计算出来的函数值都没有当前的$ans$大,我们可以直接舍弃该区间,这样下去,我们得到的$ans$值一定是越来越大的,然后可以舍弃的区间也就越来越多,从而比$O(n)$枚举每一个$a$和$b$更快,更加优秀。最终也可以得到最优解

实现基本上就是线段树+$DFS$:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 inline int read(){
 6     int sum(0);
 7     char ch(getchar());
 8     for(;ch<'0'||ch>'9';ch=getchar());
 9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
10     return sum;
11 }
12 typedef long long L;
13 struct node{
14     int l,r;
15     L maxa,maxb;
16     node *lch,*rch;
17     node():l(0),r(0),maxa(0),maxb(0),lch(NULL),rch(NULL){}
18 }a[400005],*root;
19 int n,m,cnt;
20 inline void pushup(node *rt){
21     rt->maxa=max(rt->lch->maxa,rt->rch->maxa);
22     rt->maxb=max(rt->lch->maxb,rt->rch->maxb);
23 }
24 inline void build(int l,int r,node *rt){
25     rt->l=l,rt->r=r;
26     if(l==r){
27         rt->maxa=read(),rt->maxb=read();
28         return;
29     }
30     rt->lch=&a[++cnt],rt->rch=&a[++cnt];
31     int mid((l+r)>>1);
32     build(l,mid,rt->lch);
33     build(mid+1,r,rt->rch);
34     pushup(rt);
35 }
36 inline L query_a(int l,int r,node *rt){
37     if(l<=rt->l&&rt->r<=r)
38         return rt->maxa;
39     int mid((rt->l+rt->r)>>1);
40     L ret(-0x7fffffff);
41     if(l<=mid)
42         ret=max(ret,query_a(l,r,rt->lch));
43     if(mid<r)
44         ret=max(ret,query_a(l,r,rt->rch));
45     return ret;
46 }
47 inline L query_b(int l,int r,node *rt){
48     if(l<=rt->l&&rt->r<=r)
49         return rt->maxb;
50     int mid((rt->l+rt->r)>>1);
51     L ret(-0x7fffffff);
52     if(l<=mid)
53         ret=max(ret,query_b(l,r,rt->lch));
54     if(mid<r)
55         ret=max(ret,query_b(l,r,rt->rch));
56     return ret;
57 }
58 L ans;
59 inline void dfs(L x,L y,node *rt){
60     if(rt->l==rt->r){
61         ans=max(ans,x*(rt->maxa)+y*(rt->maxb));
62         return;
63     }
64     L ans1(x*(rt->lch->maxa)+y*(rt->lch->maxb)),ans2(x*(rt->rch->maxa)+y*(rt->rch->maxb));
65     if(ans1>ans)
66         dfs(x,y,rt->lch);
67     if(ans2>ans)
68         dfs(x,y,rt->rch);
69 }
70 int main(){
71     n=read(),m=read();
72     root=&a[++cnt];
73     build(1,n,root);
74     for(int i=1;i<=m;++i){
75         L x(read()),y(read());
76         ans=-0x7fffffff;
77         dfs(x,y,root);
78         printf("%lld\n",ans);
79     }
80 }
View Code

 

posted @ 2017-08-14 09:01  Hzoi_Mafia  阅读(333)  评论(0编辑  收藏  举报
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。 ——死神