CTSC2016 时空旅行

时空旅行

题面有点长,放链接了。
LOJ 题面。

题解

显然 y,z 没有用。那么要求就是最小化 (x0-xi)2+ci

一看到二次函数形式就应该想到维护凸包。考虑这个问题的凸包要怎么维护,显然可持久化动态凸包是可行的

由于每个节点的操作对子树生效,而子树的 DFS 序是连续的,所以可以对 DFS 序做线段树分治。区间修改操作可以在 DFS 的同时解决,主要就是递归和回溯之前的操作,具体见代码。

然后由于修改互相独立,所以可以先对线段树节点建出凸包。询问先在外层排序后再放进线段树里查询,这样就不用写二分了。

时间复杂度 O(n log2 n)。

#include
using namespace std;
template T read(){
    T x=0,w=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*w;
}
template T read(T&x){
    return x=read();
}
#define co const
#define il inline
typedef long long LL;

struct Vector {LL x,y;};
il bool operator<(co Vector&a,co Vector&b){
    return a.x!=b.x?a.x tree[N<<2];
int pl[N<<2]; // edit 3: N<<2
#define lc (x<<1)
#define rc (x<<1|1)
void insert(int x,int l,int r,int ql,int qr,co Vector&v){
//  if(x==1) cerr<<"ins "<>1;
    if(ql<=mid) insert(lc,l,mid,ql,qr,v);
    if(qr>mid) insert(rc,mid+1,r,ql,qr,v);
}
void dfs(int x){
    pos[x]=++dfn;
    if(id[x]>0) last[id[x]]=dfn;
    else{
        int p=-id[x];
        if(last[p]<=dfn-1)
            insert(1,1,n,last[p],dfn-1,(Vector){2*X[p],X[p]*X[p]+C[p]});
        last[p]=0;
    }
    for(int y=to[x];y;y=next[y]) dfs(y);
    if(id[x]<0) last[-id[x]]=dfn+1;
    else{
        int p=id[x];
        if(last[p]<=dfn)
            insert(1,1,n,last[p],dfn,(Vector){2*X[p],X[p]*X[p]+C[p]});
        last[p]=0;
    }
}
void build(int x,int l,int r){
    sort(tree[x].begin(),tree[x].end());
    static Vector st[N];
    int top=0;
    for(int i=0;i<(int)tree[x].size();++i){
        while(top>=2 and cross(tree[x][i]-st[top-1],st[top]-st[top-1])>=0) --top;
        st[++top]=tree[x][i];
    }
    tree[x].assign(st+1,st+top+1);
    if(l==r) return;
    int mid=(l+r)>>1;
    build(lc,l,mid),build(rc,mid+1,r);
}

struct ask {int s,x,id;}q[N];
il bool operator<(co ask&a,co ask&b){
    return a.x>1;
    if(q.s<=mid) query(lc,l,mid,q);
    else query(rc,mid+1,r,q);
}

int main(){
    freopen("travel.in","r",stdin),freopen("travel.out","w",stdout); // travel
    read(n),read(m),read(C[1]);
    id[1]=1;
    for(int i=2;i<=n;++i){
        int opt=read(),fa=read()+1;
        next[i]=to[fa],to[fa]=i,id[i]=read()+1;
        if(!opt) read(X[id[i]]),read(),read(),read(C[id[i]]); // edit 2:id
        else id[i]=-id[i];
    }
    dfs(1),build(1,1,n);
    for(int i=1;i<=m;++i){
        int s=read()+1,x=read();
        q[i]=(ask){pos[s],x,i};
    }
    sort(q+1,q+m+1);
    for(int i=1;i<=m;++i) ans[q[i].id]=1e18,query(1,1,n,q[i]);
    for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
    return 0;
}

你可能感兴趣的:(CTSC2016 时空旅行)