loj 6034 线段游戏

题目大意:

给出若干条线段,用 (x1,y2),(x2,y2) 表示其两端点坐标,现在要求支持两种操作:

  • 0 x1 y1 x2 y2 表示加入一条新的线段 (x1,y2),(x2,y2)
  • 1 x0 询问所有线段中,x坐标在 x0 ​​ 处的最高点的 y 坐标是什么,如果对应位置没有线段,则输出 

思路:

使用李超树维护

每一个加入的线段 在它能覆盖的线段树区间中修改

修改的时候判断它是否在中点的位置更优

然后将这个区间原来维护的线段与新线段比较

不优的那个考虑下放到左右儿子区间中继续更新

查询的时候答案为经过的所有线段树的线段中最大的

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #define inf 2139062143
11 #define ll long long
12 #define MAXN 100100
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 int n,m,mx[MAXN<<2];
22 struct seg{double k,b;}tag[MAXN<<2];
23 inline void build(int k,int l,int r)
24 {
25     tag[k].k=0,tag[k].b=-inf;
26     if(l==r) return ;
27     int mid=(l+r)>>1;
28     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
29 }
30 inline void real_mdf(int k,int l,int r,seg x)
31 {
32     //cout<<k<<" "<<l<<" "<<r<<" "<<x.k<<" "<<x.b<<endl;
33     if(l==r) {if(tag[k].k*l+tag[k].b<x.k*l+x.b) tag[k]=x;return ;}
34     int mid=(l+r)>>1;
35     if(tag[k].k*mid+tag[k].b<x.k*mid+x.b) swap(tag[k],x);
36     //cout<<"i: "<<k<<" "<<l<<" "<<r<<" "<<x.k<<" "<<x.b<<endl;
37     if(tag[k].k*l+tag[k].b<x.k*l+x.b) real_mdf(k<<1,l,mid,x);
38     if(tag[k].k*r+tag[k].b<x.k*r+x.b) real_mdf(k<<1|1,mid+1,r,x);
39 }
40 inline void mdf(int k,int l,int r,int a,int b,seg x)
41 {
42     if(a>b) return ;
43     //cout<<k<<" "<<l<<" "<<r<<" "<<a<<" "<<b<<" "<<x.k<<" "<<x.b<<endl;
44     if(l==a&&r==b) {real_mdf(k,l,r,x);return ;}
45     int mid=(l+r)>>1;
46     if(b<=mid) mdf(k<<1,l,mid,a,b,x);
47     else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,x);
48     else {mdf(k<<1,l,mid,a,mid,x);mdf(k<<1|1,mid+1,r,mid+1,b,x);}
49 }
50 inline double query(int k,int l,int r,int x)
51 {
52     //cout<<x<<" "<<tag[k].k*x+tag[k].b<<endl;
53     if(l==r) return tag[k].k*x+tag[k].b;
54     int mid=(l+r)>>1;double res;
55     //cout<<k<<" "<<res<<endl;
56     if(x<=mid) res=query(k<<1,l,mid,x);
57     else res=query(k<<1|1,mid+1,r,x);
58     return max(tag[k].k*x+tag[k].b,res);
59 }
60 int main()
61 {
62     //freopen("C2.in","r",stdin);
63     n=read(),m=read();int a,b,x,y,z;double k,B;
64     build(1,1,MAXN-100);
65     for(int i=1;i<=n;i++) 
66     {
67         x=read(),y=read(),a=read(),b=read();
68         //cout<<6<<endl;
69         if(x==a) k=0,B=max(y,b);
70         else k=(double)(y-b)/(x-a),B=y-k*x;
71         //cout<<k<<" "<<b<<endl;
72         mdf(1,1,MAXN-100,max(1,min(a,x)),min(MAXN-100,max(x,a)),(seg){k,B});
73     }
74     while(m--)
75     {
76         z=read();
77         if(z) {a=read(),k=query(1,1,MAXN-100,a);printf("%.3lf\n",k<=-inf?0:k);}
78         else 
79         {
80             x=read(),y=read(),a=read(),b=read();
81             //cout<<6<<endl;
82             if(x==a) k=0,B=max(y,b);
83             else k=(double)(y-b)/(x-a),B=y-k*x;
84             //cout<<k<<" "<<b<<endl;
85             mdf(1,1,MAXN-100,max(1,min(a,x)),min(MAXN-100,max(x,a)),(seg){k,B});
86         }
87         //system("pause");
88     }
89 }
View Code

 

posted @ 2018-09-13 20:34  jack_yyc  阅读(242)  评论(0编辑  收藏  举报