zoukankan      html  css  js  c++  java
  • BZOJ 3533 [SDOI2014]向量集 (线段树维护凸包)

    题面:BZOJ传送门 洛谷传送门

    容易想到这样一个结论

    把每次插入向量$(z,w)$改为在坐标系内插入一个点$(z,w)$,并对这些点建出凸包。

    每次询问向量$(x,y)$的答案,设一条直线$l$垂直于$(x,y)$,用l去切所有已知向量构成的凸包,第一个切到的点就是最优解,根据$y$的正负来决定是从上面切还是下面切

    简单证明一下,向量点积相当于向量$(z,w)$在$(x,y)$上的投影*$|(x,y)|$,所以要找在$(x,y)$方向上最长的向量。

    我们对向量$(x,y)$所在的直线作垂线,假设垂线经过点$(z,w)$,并交$y$轴于一点$p$,那么$p$点的纵坐标*向量$(x,y)$与$y$轴的夹角就是向量$(z,w)$的投影长,为了找最长的投影所以建凸包

    然后就是维护凸包了,可题目要求强制在线,不能$CDQ$,询问$[l,r]$区间的凸包且$x$无序,可持久化splay维护凸包?

    维护可持久化凸包一般是用线段树,线段树每个区间都挂一个凸包,询问$[l,r]$区间的凸包相当于区间查询

    如果保证x有序,每个新来的点在线段树的每一层都插入,动态建出凸包。

    所有询问不会超出已知的凸包范围!

    每当线段树的一个区间被插满之后再建出凸包就行了。不会询问没建完的区间的凸包

    每次在凸包上二分即可

    时间$O(nlog^{2}n)$

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #define N1 400010
      5 #define dd double
      6 #define ll long long 
      7 using namespace std;
      8 
      9 const ll inf=0x3f3f3f3f3f3f3f3fll;
     10 const int zwz=1000000007;
     11 int gint()
     12 {
     13     int ret=0,fh=1;char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 
     19 int n,Q;
     20 ll X[N1],Y[N1];
     21 int pos[N1];//id[N1];
     22 int cmpx0(int x,int y){ if(X[x]!=X[y]) return X[x]<X[y]; else return Y[x]<Y[y];}
     23 int cmpx1(int x,int y){ if(X[x]!=X[y]) return X[x]<X[y]; else return Y[x]>Y[y];}
     24 struct OP{int x,y,l,r;}op[N1];
     25 ll ask(int i,ll x,ll y){ return X[i]*x+Y[i]*y; }
     26 
     27 struct SEG{
     28 
     29 int stk0[20][N1],stk1[20][N1],ed0[N1<<2],ed1[N1<<2],que[N1];
     30 
     31 int cmp(int a,int b,ll x,ll y)
     32 {
     33     if(!a||!b) return a+b;
     34     return (X[a]*y+Y[a]*(-x)>X[b]*y+Y[b]*(-x))?a:b;
     35 }
     36 
     37 void build0(int *s,int &tp,int l,int r)
     38 {
     39     int i,j;
     40     for(i=l;i<=r;i++) que[i-l+1]=i;
     41     sort(que+1,que+r-l+2,cmpx0);
     42     for(j=1;j<=r-l+1;j++)
     43     {
     44         i=que[j];
     45         while(tp>1&&(Y[i]-Y[s[tp-1]])*(X[s[tp]]-X[s[tp-1]])>=(Y[s[tp]]-Y[s[tp-1]])*(X[i]-X[s[tp-1]]))
     46             tp--;
     47         s[++tp]=i;
     48     }
     49 }
     50 int qup(int *s,int l,int r,int rt,ll x,ll y)
     51 {
     52     if(!ed0[rt]) build0(s,ed0[rt],l,r);
     53     if(ed0[rt]==1) return s[1];
     54     l=2,r=ed0[rt]; int mid,ans=s[1];
     55     while(l<=r)
     56     {
     57         mid=(l+r)>>1; 
     58         if(1.0*(Y[s[mid]]-Y[s[mid-1]])/(X[s[mid]]-X[s[mid-1]])>=1.0*y/x) ans=s[mid],l=mid+1;
     59         else r=mid-1;
     60     }
     61     return ans;
     62 }
     63 int qmax(int L,int R,int l,int r,int rt,int D,ll x,ll y)
     64 {
     65     if(L<=l&&r<=R) return qup(stk0[D]+l-1,l,r,rt,x,y);
     66     int mid=(l+r)>>1,ans=0,tmp;
     67     if(L<=mid) tmp=qmax(L,R,l,mid,rt<<1,D+1,x,y),ans=cmp(ans,tmp,x,y);
     68     if(R>mid) tmp=qmax(L,R,mid+1,r,rt<<1|1,D+1,x,y),ans=cmp(ans,tmp,x,y);
     69     return ans;
     70 }
     71 
     72 
     73 void build1(int *s,int &tp,int l,int r)
     74 {
     75     int i,j;
     76     for(i=l;i<=r;i++) que[i-l+1]=i;
     77     sort(que+1,que+r-l+2,cmpx1);
     78     for(j=1;j<=r-l+1;j++)
     79     {
     80         i=que[j];
     81         while(tp>1&&(Y[i]-Y[s[tp-1]])*(X[s[tp]]-X[s[tp-1]])<=(Y[s[tp]]-Y[s[tp-1]])*(X[i]-X[s[tp-1]]))
     82             tp--;
     83         s[++tp]=i;
     84     }
     85 }
     86 int qdown(int *s,int l,int r,int rt,ll x,ll y)
     87 {
     88     if(!ed1[rt]) build1(s,ed1[rt],l,r);
     89     if(ed1[rt]==1) return s[1];
     90     l=2,r=ed1[rt]; int mid,ans=s[1];
     91     while(l<=r)
     92     {
     93         mid=(l+r)>>1;
     94         if(1.0*(Y[s[mid]]-Y[s[mid-1]])/(X[s[mid]]-X[s[mid-1]])<=1.0*y/x) ans=s[mid],l=mid+1;
     95         else r=mid-1;
     96     }
     97     return ans;
     98 }
     99 int qmin(int L,int R,int l,int r,int rt,int D,ll x,ll y)
    100 {
    101     if(L<=l&&r<=R) return qdown(stk1[D]+l-1,l,r,rt,x,y);
    102     int mid=(l+r)>>1,ans=0,tmp;
    103     if(L<=mid) tmp=qmin(L,R,l,mid,rt<<1,D+1,x,y),ans=cmp(ans,tmp,x,y);
    104     if(R>mid) tmp=qmin(L,R,mid+1,r,rt<<1|1,D+1,x,y),ans=cmp(ans,tmp,x,y);
    105     return ans;
    106 }
    107 
    108 }s;
    109 ll ans;
    110 void decode(int &x){ x=x^(ans&0x7fffffff); }
    111 
    112 int de;
    113 int main()
    114 {
    115     Q=gint(); char str[10],Str[10]; scanf("%s",Str);
    116     int x,y,l,r,i,j,nn=0,a; 
    117     for(i=1;i<=Q;i++)
    118     {
    119         scanf("%s",str);
    120         if(str[0]=='A'){
    121             op[i].x=gint(), op[i].y=gint(); nn++; pos[i]=nn; //id[nn]=i;
    122         }else{
    123             op[i].x=gint(), op[i].y=gint();
    124             op[i].l=gint(), op[i].r=gint();
    125         }
    126     }
    127     for(i=1;i<=Q;i++)
    128     {
    129         x=op[i].x; y=op[i].y; l=op[i].l; r=op[i].r;
    130         if(!l&&!r){
    131             if(Str[0]!='E') decode(x), decode(y); X[pos[i]]=x; Y[pos[i]]=y;
    132         }else{
    133             if(Str[0]!='E') decode(x), decode(y), decode(l), decode(r);
    134             if(y>0) a=s.qmax(l,r,1,nn,1,0,-y,x); 
    135             else a=s.qmin(l,r,1,nn,1,0,-y,x); 
    136             ans=X[a]*x+Y[a]*y;
    137             printf("%lld
    ",ans);
    138         }
    139     }
    140     return 0;
    141 }
  • 相关阅读:
    为什么不直接使用socket ,还要定义一个新的websocket 的呢
    js-权威指南-Web套接字
    CSS-蜂窝状展示区域(多个六边形)的一种实现方式
    MQTT入门介绍
    【珍惜时间】vuepro
    搭建react的vw架构时候报 Cannot load preset "advanced".
    跟我一起使用create-react-app脚手架搭建vw-layout解决方案
    【珍惜时间】iReport
    vue中 给router-view 组件的 绑定 key 的原因
    SQL Server Index详解
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10359419.html
Copyright © 2011-2022 走看看