acm 2015北京网络赛 F Couple Trees 主席树+树链剖分

提交

题意:给了两棵树,他们的跟都是1,然后询问,u,v 表 示在第一棵树上在u点往根节点走 , 第二棵树在v点往根节点走,然后求他们能到达的最早的那个共同的点

解:

我们将第一棵树进行书链剖,然后第二棵树采用主席树,他的信息来自他的父亲节点,每个点存他在第一棵树 树链剖分后的位置,这样我们每次查询uv的时候我们只要 我们选取u和top[u]这段区间在主席树v这颗树上找,在这个区间能取到的最大值,一旦存在,这个最大值就我们要的,这个点保存着他到根节点这条路上所有点在第一棵树剖分后的位置

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int maxn=100005;
const int MMAXN=100005*20;
int H[maxn],to[maxn*2],nx[maxn*2],numofE;
int son[maxn],depth[maxn],fa[maxn],num[maxn],top[maxn];
int p[maxn],fp[maxn],pos,sizoftree;
int Ls[MMAXN],Rs[MMAXN],Mav[MMAXN],T[maxn],depth2[maxn];
void init(int n)
{
    sizoftree=pos=numofE=0;
    for(int i=0; i<=n; i++)H[i]=0;
    T[0]=Ls[0]=Rs[0]=Mav[0]=sizoftree=0;
}
void add(int u,int v)
{
    numofE++;
    to[numofE]=v;
    nx[numofE]=H[u];
    H[u]=numofE;
}

void dfs(int cur, int per, int dep)
{

    depth[cur]=dep;
    son[cur]=-1;
    fa[cur]=per;
    num[cur]=1;
    for(int i=H[cur]; i; i=nx[i])
    {
        int tt=to[i];
        if(tt==per)continue;
        dfs(tt,cur,dep+1);
        num[cur]+=num[tt];
        if(son[cur]==-1 || num[ son[cur] ]<num[tt]) son[cur]=tt;
    }
}
void finde(int cur, int per, int tp)
{
    top[cur]=tp;
    pos++;
    p[cur]=pos;
    fp[pos]=cur;
    if(son[cur]!=-1) finde(son[cur],cur,tp);
    for(int i=H[cur]; i; i=nx[i])
    {
        int tt=to[i];
        if(tt==per||tt==son[cur])continue;
        finde(tt,cur,tt);
    }
}
void insert(int L, int R, int K,int pre ,int &x)
{
    x=++sizoftree;
    Ls[x]=Ls[pre];
    Rs[x]=Rs[pre];
    Mav[x]=max( Mav[pre],K);
    if(L==R)return ;
    int mid=(L+R)>>1;
    if(K<=mid)insert(L,mid,K,Ls[pre],Ls[x]);
    else insert(mid+1,R,K,Rs[pre],Rs[x]);
}
int cL,cR;
int query(int L, int R,int root)
{
    if(cL<=L&&R<=cR)return Mav[root];
    if(Mav[root]==0)return 0;
    int mid=(L+R)>>1;
    int a1=0,a2=0;
    if(cL<=mid)a1=query(L,mid,Ls[root]);
    if(cR>mid)a2=query(mid+1,R,Rs[root]);
    return max(a1,a2);
}
int solve(int u, int v,int n)
{
    int fu=top[u];
    int ret;
    while(true)
    {
        cL=p[fu];cR=p[u];
        ret=query(1,n,T[v]);
        if(ret)break;
        u=fa[fu];
        fu=top[u];
    }
    return fp[ret];
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
         init(n);
         for(int i=2; i<=n; i++)
         {
             int u;
             scanf("%d",&u);
             add(i,u); add(u,i);
         }
         dfs(1,1,1);
         finde(1,1,1);
         depth2[1]=1;
         insert(1,n,1,T[0],T[1]);
         for(int i=2; i<=n; i++)
         {
             int u;
             scanf("%d",&u);
             depth2[i]=depth2[u]+1;
             insert(1,n,p[i],T[u],T[i]);
         }
         int ans=0;
         for(int i=0; i<m; i++)
         {
             int u,v;
             scanf("%d%d",&u,&v);
             u=(u+ans)%n+1;
             v=(v+ans)%n+1;
             ans=solve(u,v,n);
             printf("%d %d %d\n",ans,depth[u]-depth[ans]+1,depth2[v]-depth2[ans]+1);
         }

    }
    return 0;
}
时间: 2024-12-21 19:51:19

acm 2015北京网络赛 F Couple Trees 主席树+树链剖分的相关文章

2015北京网络赛 F Couple Trees 暴力倍增

Couple Trees Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/1232 Description "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they look like a couple leaning on each other.

(中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

"Couple Trees" are two trees, a husband tree and a wife tree. They are named because they look like a couple leaning on each other. They share a same root, and their branches are intertwined. In China, many lovers go to the couple trees. Under t

Hiho 1232 北京网络赛 F Couple Trees

给两颗标号从1...n的树,保证标号小的点一定在上面.每次询问A树上的x点,和B树上的y点同时向上走,最近的相遇点和x,y到这个点的距离. 比赛的时候想用倍增LCA做,但写渣了....后来看到题解是主席树就写了一发 呆马: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #inclu

2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)

#1231 : Border Length 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Garlic-Counting Chicken is a special species living around the Lake of Peking University. A Garlic-Counting Chicken always flies out from home in the morning, goes to some fixed points looki

2015北京网络赛 Couple Trees 倍增算法

2015北京网络赛 Couple Trees 题意:两棵树,求不同树上两个节点的最近公共祖先 思路:比赛时看过的队伍不是很多,没有仔细想.今天补题才发现有个 倍增算法,自己竟然不知道.  解法来自 qscqesze ,这个其实之前如果了解过倍增的话还是不是很难,不过这题的数据也不是很给力,极限数据理论上是过不了的.  其他解法有树链剖分?并不是很清楚.就这样水过了吧... 1 #include <iostream> 2 #include <cstdio> 3 #include &l

2015北京网络赛 D-The Celebration of Rabbits 动归+FWT

2015北京网络赛 D-The Celebration of Rabbits 题意: 给定四个正整数n, m, L, R (1≤n,m,L,R≤1000). 设a为一个长度为2n+1的序列. 设f(x)为满足x≤ai≤m+x且ai的异或和为0 的序列a的个数. 求 ∑Rx=Lf(x)mod1000000007 思路:因为对于每一个第一次分配后的a序列对应唯一的x,所以我们就枚举x然后在求序列的个数.

2015北京网络赛A题The Cats&#39; Feeding Spots

题意:给你一百个点,找个以这些点为中心的最小的圆,使得这个圆恰好包含了n个点,而且这个圆的边界上并没有点 解题思路:暴力枚举每个点,求出每个点到其他点的距离,取第n大的点,判断一下. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<memory.h> 6 using namespace std; 7 const i

hihoCoder #1388 : Periodic Signal ( 2016 acm 北京网络赛 F题)

时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device which can send a particular 1 second signal repeatedly. The signal is A0 ... An-1 under n Hz sampling. One day, the device fell on the ground accidenta

2015北京网络赛 G Boxes BFS+打表

G Boxes 题意:n个位置摆有n个箱子,每次移动只能把相邻的垒起来,且上面的必须小于下面的.求摆成升序需要移动多少步. 思路:这里的n很小,只有7.但是bfs最快的情况需要2s左右,所以就打表了. 诡异的是n = 6时居然都跑不出来都超时,连6也打了个表. 1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <