• [CTSC2016]时空旅行(线段树+凸包)


    应该是比较套路的,但是要A掉仍然不容易。

    下面理一下思路,思路清楚了也就不难写出来了。

    0.显然y,z坐标是搞笑的,忽略即可。

    1.如果x不变,那么直接set即可解决。

    2.考虑一个空间和询问x0,通过化式子发现实际上就是:把每个星球看成一个一次函数,其实是在询问这个空间内的所有一次函数在x0处的最小值。

    3.这个显然是一个凸包,所以我们需要对每个空间维护一个凸包,由空间整体呈树状,可以想到用DFS序+线段树维护区间。

    4.预处理出每个星球的存在范围,在线段树上永久化标记。查询时依次递归求最小值。

    5.关于线段树上如何存凸包,可以先扫一遍预留出空间,也可以直接像http://www.cnblogs.com/HocRiser/p/8549456.html一样用vector存,后者可能会慢一点,开了读入外挂就过了。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<algorithm>
     4 #define ls (x<<1)
     5 #define rs (ls|1)
     6 #define lson ls,L,mid
     7 #define rson rs,mid+1,R
     8 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     9 typedef long long ll;
    10 using namespace std;
    11 
    12 const int N=500010;
    13 const ll inf=1000000000000000000ll;
    14 int n,m,cnt,x,y,c,tim,op,fr,d,id[N],L[N],R[N],X[N],K[N];
    15 int h[N],nxt[N],pos[N],to[N],st[N<<2],ed[N<<2],q[N];
    16 ll a[N],b[N],ans[N];
    17 vector<int>T[N<<2],V[N];
    18 
    19 ll rd(){
    20     ll x=0; bool t=0; char ch=getchar();
    21     while (ch<'0' || ch>'9') t|=(ch=='-'),ch=getchar();
    22     while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    23     if (t) return -x; else return x;
    24 }
    25 
    26 bool cmp0(int x,int y){ return L[x]<L[y]; }
    27 bool cmp1(int x,int y){ return a[x]>a[y] || (a[x]==a[y] && b[x]>b[y]); }  
    28 bool cmp2(int a,int b){ return X[a]<X[b]; }
    29 bool Cmp(int x,int y,int z){ return ((b[y]-b[x])*(a[y]-a[z])>=(b[z]-b[y])*(a[x]-a[y])); }
    30 
    31 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
    32 
    33 void dfs(int x){ L[x]=++tim; for (int i=h[x]; i; i=nxt[i]) dfs(to[i]); R[x]=tim; }
    34 
    35 void build(int x,int L,int R){
    36     ed[x]=-1;
    37     if (L==R) { pos[L]=x; return; }
    38     int mid=(L+R)>>1; build(lson); build(rson);
    39 }
    40 
    41 void ins(int x,int L,int R,int l,int r,int k){
    42     if (L==l && r==R){
    43         int &j=ed[x];
    44         for (; st[x]<j && Cmp(T[x][j-1],T[x][j],k); j--,T[x].pop_back());
    45         j++; T[x].push_back(k);
    46         return;
    47     }
    48     int mid=(L+R)>>1;
    49     if (r<=mid) ins(lson,l,r,k);
    50     else if (l>mid) ins(rson,l,r,k);
    51         else ins(lson,l,mid,k),ins(rson,mid+1,r,k);
    52 }
    53 
    54 ll que(int k,int x){
    55     ll ans=inf;
    56     for (int i=pos[k]; i; i>>=1){
    57         int &j=st[i];
    58         for (; j<ed[i] && (a[T[i][j]]-a[T[i][j+1]])*x>=b[T[i][j+1]]-b[T[i][j]]; j++);
    59         if (j<=ed[i]) ans=min(ans,a[T[i][j]]*x+b[T[i][j]]);
    60     }
    61     return ans;
    62 }
    63 
    64 int main(){
    65     freopen("travel.in","r",stdin);
    66     freopen("travel.out","w",stdout);
    67     n=rd(); m=rd(); b[1]=rd(); id[1]=1;
    68     rep(i,2,n){
    69         op=rd(); fr=rd()+1; d=rd()+1; add(fr,i);
    70         if (op) V[d].push_back(i);
    71         else id[d]=i,x=rd(),rd(),rd(),c=rd(),a[d]=-2ll*x,b[d]=1ll*x*x+c;
    72     }
    73     dfs(1); build(1,1,n);
    74     rep(i,1,n) q[i]=i; sort(q+1,q+n+1,cmp1);
    75     rep(l,1,n) if (id[q[l]]){
    76         int i=q[l];
    77         sort(V[i].begin(),V[i].end(),cmp0); int k=L[id[i]];
    78         for (vector<int>::iterator it=V[i].begin(); it!=V[i].end(); k=R[*it]+1,it++)
    79             if (k<L[*it]) ins(1,1,n,k,L[*it]-1,i);
    80         if (k<=R[id[i]]) ins(1,1,n,k,R[id[i]],i);
    81     }
    82     rep(i,1,m) q[i]=i,x=rd(),y=rd(),K[i]=L[x+1],X[i]=y;
    83     sort(q+1,q+m+1,cmp2);
    84     rep(i,1,m) ans[q[i]]=que(K[q[i]],X[q[i]])+1ll*X[q[i]]*X[q[i]];
    85     rep(i,1,m) printf("%lld
    ",ans[i]);
    86     return 0;
    87 }
  • 相关阅读:
    springboot整合Swagger2
    FastJson会把哪些字符串解析为null
    BitMap再再体验之布隆过滤器
    如何利用windows自带的画图工具拼接图片
    BitMap再体验之排序
    BitMap 初体验
    Chrome 隐藏最常访问的网站
    idea同一个项目不同端口启动
    ubuntu16搭建harbor镜像库
    virtualbox硬盘扩容
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8999556.html
Copyright © 2020-2023  润新知