zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    重定向与转发比较
    servlet_5
    servlet_4
    servlet_3
    字符串的操作以及格式化的操作
    2019的Python
    函数2
    函数
    文件操作
    集合 set
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7590334.html
Copyright © 2011-2022 走看看