题意:支持插入直线,询问某个x坐标下最大的直线对应的y值(x为整数)

首先为整数,意味着可以用维护下标的数据结构维护,其次我们分析发现对于两条直线,至多相交一次,考虑最后的答案一定为类似凸壳的东西,一条线段至多把凸壳分为三段,那么就可以递归到左边和右边去做,O(mlogn)即可。

附数据生成器:

输入:一个m问题数(m<=100000),奇数 y=kx+b,k,b(k,b小于等于100),偶数 x(100000>=x>=1)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdlib> 
 6 
 7 using namespace std;
 8 
 9 int random(int x)
10 {
11     return rand()*rand()%x;
12 } 
13 int main()
14 {
15         srand(1);
16     int n=100000,m=100000;
17     printf("%d\n",m); 
18     for(int i=1;i<=m;i++)
19     {
20         if(i%2==0)
21         {
22             printf("%d\n",random(n)+1);
23             continue;
24         }
25         int k=random(100)+1,b=random(100)+1;
26         if(random(100)<50)k=-k;
27         if(random(100)<50)b=-b;
28         printf("%d %d\n",k,b);
29     }
30     return 0;
31 } 
数据生成器

附对应代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 const int maxn=100005;
 7 using namespace std;
 8 
 9 struct mydata
10 {
11     int son[2];
12     int k,b; 
13 };
14 int inf=1e9;
15 struct mytree
16 {
17     int np,rt,n;
18     mydata c[maxn<<1];
19     void build(int &now,int l,int r)
20     {
21         now=++np;
22         c[now]=(mydata){{0,0},0,-inf};
23         if(l==r)return;
24         int m=(l+r)/2;
25         build(c[now].son[0],l,m);
26         build(c[now].son[1],m+1,r);
27     }
28     void update(int now,int l,int r,int x,int y,int k,int b)
29     {
30         if(x<=l&&r<=y)
31         {
32             int v1=l*c[now].k+c[now].b;
33             int v2=r*c[now].k+c[now].b;
34             int v3=l*k+b;
35             int v4=r*k+b;
36             if(v1<=v3&&v2<=v4)
37             {
38                 c[now].k=k;
39                 c[now].b=b;
40                 return;
41             }
42             else if(v1>=v3&&v2>=v4)return;
43         }
44         
45         int m=(l+r)/2;
46         if(y<=m)update(c[now].son[0],l,m,x,y,k,b);
47         else if(x>=m+1)update(c[now].son[1],m+1,r,x,y,k,b);
48         else
49         {
50             update(c[now].son[0],l,m,x,y,k,b);
51             update(c[now].son[1],m+1,r,x,y,k,b);
52         }
53     }
54     int query(int now,int l,int r,int x)
55     {
56         int tmp=c[now].k*x+c[now].b;
57         if(l==r)return tmp;
58         
59         int m=(l+r)/2;
60         if(x<=m)return max(tmp,query(c[now].son[0],l,m,x));
61         else return max(tmp,query(c[now].son[1],m+1,r,x));
62     }
63 }c;
64 int main()
65 {
66     int n=100000,m;
67     scanf("%d",&m);
68     c.build(c.rt,1,n);
69     int x,ai,bi;
70     for(int i=1;i<=m;i++)
71     {
72         int tmp=-1e9;
73         if(i%2==0)
74         {
75             scanf("%d",&x);
76             printf("%d\n",c.query(c.rt,1,n,x));
77             continue; 
78         }
79         scanf("%d%d",&ai,&bi);
80         c.update(c.rt,1,n,1,n,ai,bi);
81     }
82     return 0;
83 } 
View Code