bzoj3165 segment 超哥线段树

Posted Loser Of Life

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3165 segment 超哥线段树相关的知识,希望对你有一定的参考价值。

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3165

题意:动态增加线段,求出横坐标纵坐标最高的被覆盖点所在线段。

这个题要用到李超线段树(orz李超)……大概这是李超那篇论文出现后第二年的题?不管了直接介绍这一数据结构。李超线段树的目的就是查询出每个点被线段覆盖的情况,操作无非就是插入线段和查询两件事。

插入线段:首先计算出原有线段和现在线段在这个区间之内的函数值,如果新线段一直大直接修改返回,如果一直小也直接返回,否则递归修改至单点或全部返回为止。

查询线段:不断地递归查询,从根节点整条数轴一直查询到单点,期间找到最值就进行修改。

可以证明,单次修改时间复杂度$O(log^2n)$,单次查询时间复杂度$O(logn)$,因此复杂度完全足够。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<map>
 6 using namespace std;
 7 const int maxn=100005,maxp=40005;const double eps=1e-9;
 8 struct node
 9 {
10     double k,b;int id;bool vis;
11 }S[maxn<<2];
12 int dcmp(double x)
13 {
14     return (x>eps)-(x<-eps);
15 }
16 #define mid ((l+r)>>1)
17 #define lc root<<1
18 #define rc root<<1|1
19 #define lson lc,l,mid
20 #define rson rc,mid+1,r
21 inline void solve(int root,int l,int r,int idx,double k,double b)
22 {
23     if(!S[root].vis)
24     {
25         S[root].k=k,S[root].b=b,S[root].id=idx,S[root].vis=1;
26         return;
27     }
28     double y0=S[root].k*l+S[root].b,y1=k*l+b,y2=S[root].k*r+S[root].b,y3=k*r+b;
29     if(dcmp(y1-y0)>0&&dcmp(y3-y2)>0)
30     {
31         if(dcmp(k-S[root].k)==0&&dcmp(b-S[root].b)==0)return;
32         S[root].k=k,S[root].b=b,S[root].id=idx;
33         return;
34     }
35     if(dcmp(y1-y0)<=0&&dcmp(y3-y2)<=0)return;
36     solve(lson,idx,k,b);solve(rson,idx,k,b);
37 }
38 inline void insert(int root,int l,int r,int L,int R,int idx,double k,double b)
39 {
40     if(L<=l&&r<=R){solve(root,l,r,idx,k,b);return;}
41     if(L<=mid)insert(lson,L,R,idx,k,b);if(R>mid)insert(rson,L,R,idx,k,b);
42 }
43 inline void insert(int x0,int x1,int y0,int y1,int num)
44 {
45     int L=x0,R=x1;double k=1.0*(y1-y0)/(1.0*(x1-x0)),b=y0-x0*k;int idx=num;insert(1,1,maxp,L,R,idx,k,b);
46 }
47 double ans;int ans_id;
48 inline void query(int root,int l,int r,int pos)
49 {
50     double x=S[root].k*pos+S[root].b;
51     if(dcmp(x-ans)>0||dcmp(x-ans)==0&&S[root].id<ans_id)ans=x,ans_id=S[root].id;
52     if(l==r)return;
53     if(pos<=mid)query(lson,pos);else query(rson,pos);
54 }
55 int a[maxn],id[maxn];
56 int haha()
57 {
58     int n;scanf("%d",&n);int lastans=0;
59     int opt,x0,y0,x1,y1,x,num=0;
60     while(n--)
61     {
62         scanf("%d",&opt);
63         if(!opt)
64         {
65             scanf("%d",&x),x=((x+lastans-1)%39989+1);
66             ans=ans_id=0;query(1,1,maxp,x);
67             if(ans<a[x]||ans==a[x]&&id[x]<ans_id)ans_id=id[x];
68             printf("%d\n",lastans=ans_id);
69         }
70         else
71         {
72             num++;scanf("%d%d%d%d",&x0,&y0,&x1,&y1);
73             x0=(x0+lastans-1)%39989+1,y0=(y0+lastans-1)%(int)1e9+1,x1=(x1+lastans-1)%39989+1,y1=(y1+lastans-1)%(int)1e9+1;
74             if(x0>x1)swap(x0,x1),swap(y0,y1);
75             if(x0==x1)
76             {
77                 if(max(y0,y1)>a[x0])a[x0]=max(y0,y1),id[x0]=num;
78             }
79             else insert(x0,x1,y0,y1,num);
80         }
81     }
82 }
83 int sb=haha();
84 int main(){;}
bzoj3165

 

以上是关于bzoj3165 segment 超哥线段树的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj 3165: [Heoi2013]Segment

[bzoj3165] [HEOI2013]Segment

P4097 [HEOI2013]Segment(李超树)

BZOJ 3165: [Heoi2013]Segment

Bzoj 3165 [Heoi2013]Segment题解

BZOJ 1568: [JSOI2008]Blue Mary开公司(超哥线段树)