Luogu P5416 [CTSC2016]タイムトラベル(セグメントツリーのパーティション)

トピックは
質問の意味を簡素化:あなたは維持する必要があります\(\ n)でセット、要素のタプルの集合\((X-を、V)\) コレクション\は(私は\)元ファッションコレクションに基づいて生成された\(P_I \)を展開した後、サンプルとして、あるいは新しいコレクションを取得するための要素を削除します。そこ\(Q \)時間はすべての与えられ尋ねた\(Y \)とのセットを指定\(私は\) セットからの要件\は(私は\)最小限に抑えるために、要素を見つける\を((X-Y )^ 2 + V \)
第1の分割式\((XY)^ 2 = X ^ + V ^ 2 + Y + 2-2xy Vの\) それに等しくなるように(K \)\すなわち\(X ^ 2 + y ^ 2-2xy + V K = \)
転位が持っている\(2yx + K = X ^ Y ^ 2 + 2 V \ +) と見なすことができる\((X、X ^ 2 + y ^ 2 + V)\) 決定点、\(2Y \)勾配であり、\(K \)のように\(Y \)軸切片。これは凸包を維持するために解決することができます。
私たちは知っているという点で、すべての要素\(DFS \)シーケンスは、範囲の部分の形で表示されます。
各点は、追加または削除にかかわらず、要素の新しい範囲をもたらすので、間隔の総数がされる(O(n)を\)\です。
要素\(X \)昇順のセグメントツリーの挿入後は、各ノードは、凸包を維持します。
プレス問い合わせ\(Y \)昇順で、しかしは、凸状フロントハウジング値の各操作への直接アクセスを可能にすることができます。

#include<bits/stdc++.h>
#define LL long long
#define db double
#define pb push_back
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
#define INF 1e18
using namespace std;
const int N=500007;
int L[N<<2],R[N<<2],t[N],dfn[N],T[N],n,m,Time;
LL C[N],ans[N],val[N];
vector<int>G[N],al[N],ar[N],w[N<<2];
struct node{LL x,val,id;}a[N];
int cmp(int a,int b){return val[a]<val[b];}
int operator<(node a,node b){return a.val<b.val;}
LL min(LL a,LL b){return a<b? a:b;}
db K(int x ,int y){return (val[x]*val[x]+C[x]-val[y]*val[y]-C[y])/(db)(val[x]-val[y]);}
void dfs(int u,int fa)
{
    dfn[u]=++Time;
    if(T[u]>0) al[T[u]].pb(Time);
    if(T[u]<0) ar[-T[u]].pb(Time-1);
    for(int i=G[u].size()-1,v;~i;--i) if((v=G[u][i])^fa) dfs(v,u);
    if(T[u]>0) ar[T[u]].pb(Time);
    if(T[u]<0) al[-T[u]].pb(Time+1);
}
void build(int p,int l,int r)
{
    L[p]=0,R[p]=-1;
    if(l==r) return ;
    build(ls,l,mid),build(rs,mid+1,r);
}
void update(int p,int l,int r,int ql,int qr,int P)
{
    if(ql==l&&r==qr)
    {
    while(w[p].size()<=R[p]+5) w[p].pb(0);
    if(L[p]<=R[p]&&val[w[p][R[p]]]==val[P])
    {
        if(C[w[p][R[p]]]<=C[P]) return ;
        --R[p];
    }
    while(L[p]<R[p]&&K(w[p][R[p]],P)<K(w[p][R[p]],w[p][R[p]-1])) --R[p];
    w[p][++R[p]]=P;
    return ;
    }
    if(qr<=mid) update(ls,l,mid,ql,qr,P);
    else if(ql>mid) update(rs,mid+1,r,ql,qr,P);
    else update(ls,l,mid,ql,mid,P),update(rs,mid+1,r,mid+1,qr,P);
}
LL query(int p,int l,int r,int x,LL t,LL sum)
{
    LL ans=INF;
    while(L[p]<R[p]&&K(w[p][L[p]],w[p][L[p]+1])<=2.0*t) ++L[p];
    if(L[p]<=R[p]&&w[p].size()>0) ans=(t-val[w[p][L[p]]])*(t-val[w[p][L[p]]])+C[w[p][L[p]]];
    ans=min(ans,sum);
    if(l==r) return ans;
    return x<=mid? query(ls,l,mid,x,t,ans):query(rs,mid+1,r,x,t,ans);
}
int main()
{
    int i,j,k,u,x,opt,l,r;
    scanf("%d%d%lld",&n,&m,&C[0]);
    for(i=1;i<n;++i) scanf("%d%d%d",&opt,&u,&x),G[u].pb(i),(opt? (T[i]=-x):(T[i]=x,scanf("%lld%d%d%lld",&val[x],&u,&u,&C[x])));
    dfs(0,0),build(1,1,n);
    for(i=1;i<=n;++i) t[i]=i;
    sort(t+1,t+n+1,cmp),update(1,1,n,1,n,0);
    for(i=1;i<=n;++i) for(k=t[i],j=0;j<al[k].size();++j) if((l=al[k][j])<=(r=ar[k][j])) update(1,1,n,l,r,k);
    for(i=1;i<=m;++i) scanf("%lld%lld",&a[i].x,&a[i].val),a[i].id=i;
    sort(a+1,a+m+1);
    for(i=1;i<=m;++i) ans[a[i].id]=query(1,1,n,dfn[a[i].x],a[i].val,INF);
    for(i=1;i<=m;++i) printf("%lld\n",ans[i]);
}

おすすめ

転載: www.cnblogs.com/cjoierShiina-Mashiro/p/11519553.html