hihoCoder #1381 : Little Y's Tree

http://hihocoder.com/problemset/problem/1381

 

A Conclusion: A set diameter of a - b, is set diameter B c - d, then the diameters of the collection A∪B is one of six levels:

a--b  c--d  a--c  a--d  b--c  b--d

 

A broken edge interval corresponding to a period taken from the sequence tree dfs

The diameter of any section of the maintenance interval dfs sequence segment tree with

If [1,10] is broken [1,4] [3,4] [7,8]

The answer is a diameter [1,2] + [3,4] diameter of + [5,6] ∪ [9,10] diameter of + [7,8] diameter

#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001
typedef long long LL;

int n;
int tot,front[N],nxt[N<<1],to[N<<1],val[N<<1];

int lo2[N];

int dep[N],dy[N],fa[N][18];
LL dis[N];
int ll[N],rr[N];

vector<int>inc[N];
int st[N],top;

int a[N],bin[N],cnt;
LL ans;

struct node
{
    int a,b;
    LL dis;
}tr[N<<2];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w;
}

void init()
{
    read(n);
    int u,v,w;
    for(int i=1;i<n;++i)
    {
        read(u); read(v); read(w);
        add(u,v,w);
    }
}

void dfs(int x)
{
    ll[x]=++tot;
    dy[tot]=x;
    int t;
    for(int i=front[x];i;i=nxt[i])
    {
        t=to[i];
        if(fa[t][0]) continue;
        fa[t][0]=x;
        dis[t]=dis[x]+val[i];
        dep[t]=dep[x]+1;
        dfs(t);
    }
    rr[x]=tot;
}

void pre()
{
    for(int i=2;i<=n;++i) lo2[i]=lo2[i>>1]+1; 
    fa[1][0]=-1;
    tot=0;
    dfs(1);
    int m=lo2[n]; 
    fa[1][0]=0; 
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            fa[i][j]=fa[fa[i][j-1]][j-1];
            
}

int getlca(int x,int y)
{
    int m=lo2[dep[x]];
    for(int i=m;i>=0;--i)
        if(ll[fa[x][i]]>ll[y]) x=fa[x][i];
    return fa[x][0];
}

LL getdis(int x,int y)
{
    x=dy[x];
    y=dy[y];
    if(x==y) return 0;
    if(ll[x]<ll[y]) swap(x,y);
    int lca=getlca(x,y);
    if(lca==y) return dis[x]-dis[y];
    return dis[x]+dis[y]-dis[lca]*2;
}

node unionn(node p,node q)
{
    node t1=(node){p.a,q.a,getdis(p.a,q.a)};
    node t2=(node){p.a,q.b,getdis(p.a,q.b)};
    node t3=(node){p.b,q.a,getdis(p.b,q.a)};
    node t4=(node){p.b,q.b,getdis(p.b,q.b)};
    node t=p;
    if(q.dis>t.dis) t=q;
    if(t1.dis>t.dis) t=t1;
    if(t2.dis>t.dis) t=t2;
    if(t3.dis>t.dis) t=t3;
    if(t4.dis>t.dis) t=t4;
    return t;    
}

void build(int k,int l,int r)
{
    if(l==r)
    {
        tr[k].a=tr[k].b=l;
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tr[k]=unionn(tr[k<<1],tr[k<<1|1]);
}

bool cmp(int p,int q)
{
    return ll[p]<ll[q];
}

node query(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr) return tr[k];
    int mid=l+r>>1;
    if(opr<=mid) return query(k<<1,l,mid,opl,opr);
    if(opl>mid) return query(k<<1|1,mid+1,r,opl,opr);
    node tmp1=query(k<<1,l,mid,opl,opr);
    node tmp2=query(k<<1|1,mid+1,r,opl,opr);
    return unionn(tmp1,tmp2);    
}

void dfs2(int x)
{
    int l=ll[x],m=inc[x].size(),t;
    node tmp,mx;
    mx.a=mx.b=ll[x];
    mx.dis=0;
    for(int i=0;i<m;++i)
    {
        t=inc[x][i];
        if(ll[t]!=l)
        {
            tmp=query(1,1,n,l,ll[t]-1);
            mx=unionn(mx,tmp);
        }
        dfs2(t);
        l=rr[t]+1;
    }
    if(l!=rr[x]+1) 
    {
        tmp=query(1,1,n,l,rr[x]);
        mx=unionn(mx,tmp);
    }
    ans+=mx.dis;    
}

void solve()
{
    int m,k,x,y;
    read(m);
    while(m--)
    {
        for(int i=1;i<=cnt;++i) inc[bin[i]].clear();
        cnt=ans=0;
        st[top=1]=1;
        read(k);
        for(int i=1;i<=k;++i) 
        {
            read(x);
            x<<=1;
            if(ll[to[x]]<ll[to[x-1]]) y=to[x-1];
            else y=to[x];
            a[i]=y;
        }
        sort(a+1,a+k+1,cmp);
        for(int i=1;i<=k;++i)
        {
            y=a[i];
            while(!(ll[y]>=ll[st[top]] && rr[y]<=rr[st[top]])) top--;
            inc[st[top]].push_back(y);
            bin[++cnt]=st[top];
            st[++top]=y; 
        }
        dfs2(1);
        cout<<ans<<'\n';
    }
}

int main()
{
    init();
    pre();
    build(1,1,n);
    solve();
} 

 

Time limit: 24000ms
A single point of time: 4000ms
Memory Limit: 512MB

description

Y has a small tree of n nodes, each edge has a positive edge weights.

J has a small query q, each J can delete this small tree of k edges, the tree is divided into a k + 1 th block communication. J want to know each small block in communication distance and the farthest point.

Inquiry here is independent of each other, i.e., each time the operation in the original tree small Y.

Entry

A first line integer n, each row next three integers n-1 line u, v, w, which represents the i-th row of the i-th Collage weight W i , connected to the U i , V i points.

Next, a line integer q, q represents groups have asked.

For each query, the first line of a positive integer k, k different integers between 1 to n-1 The next line indicates the number of edges removed.

1<=n,q,Σk<=105, 1<=w<=109

Export

A total of q rows, each row represents an integer answer queries.

Sample input
5
1 2 2
2 3 3
2 4 4
4 5 2
3
4 1 2 3 4
1 4
2 2 3
Sample Output
0
7
4

Guess you like

Origin www.cnblogs.com/TheRoadToTheGold/p/11881432.html