繁华模拟赛 约会

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define debug(x) cout<<#x<<"="<<x<<endl
#define MP(x,y) make_pair(x,y)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
int fa[N][20],dep[N],maxd,lg;
int n,sz[N];
vector<int> G[N];
void initlca()
{
    int i,j;
    lg=int(log(maxd)/log(2)+0.5);
    for(j=1;j<=lg;j++)
        for(i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
}

inline int lca(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    int i;
    //debug(lg);
    for(i=lg;i>=0;i--)
        if(dep[fa[v][i]]>=dep[u])
            v=fa[v][i];
    if(u==v) return u;
    for(i=lg;i>=0;i--)
        if(fa[v][i]!=fa[u][i])
            u=fa[u][i],v=fa[v][i];
    return fa[v][0];
}

void dfs(int x)
{
    int i,len=G[x].size(),v;
    maxd=max(maxd,dep[x]);
    for(i=0;i<len;i++)
    {
        v=G[x][i];
        if(v!=fa[x][0])
        {
            dep[v]=dep[x]+1;
            fa[v][0]=x;
            dfs(v);
            sz[x]+=sz[v];
        }
    }
    sz[x]++;
}

int get(int x,int b)
{
    for(int i=lg;i>=0;i--)
        if(b&(1<<i))
            x=fa[x][i];
    return x;
}

int main()
{
    int a,b,m,c,d1,d2,d,y,i;
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
    cin>>n;
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    fa[1][0]=1,dep[1]=1;
    dfs(1);
    initlca();
    //debug(fa[6][0]);
    //debug(fa[2][0]);
    //debug(dep[2]);
    //debug(dep[6]);
    //debug(lca(2,15));
    //return 0;
    cin>>m;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        c=lca(a,b);
        //debug(a);
        //debug(c);
        d=dep[a]-dep[c]+dep[b]-dep[c];
        if(d&1)
            printf("0\n");
        else if(a==b)
            printf("%d\n",n);
        else
        {
            d1=dep[a]-dep[c];
            d2=dep[b]-dep[c];
            d=d/2;
            if(d1==d)
            {
                c=get(a,d-1);
                y=get(b,d-1);
                printf("%d\n",n-sz[c]-sz[y]);
            }
            else
            {
                //debug(d1),debug(d2),debug(d);
                if(d1>d2)
                    c=get(a,d),y=get(a,d-1);
                else c=get(b,d),y=get(b,d-1);
                //debug(c);
                //debug(y);
                printf("%d\n",sz[c]-sz[y]);
            }
        }
    }
    return 0;
}
// davidlee1999WTK 2015/
// srO myk Orz
//ios::sync_with_stdio(false);
/*
15
1 2
1 3
1 4
2 5
2 6
2 7
5 8
6 9
9 14
14 15
7 10
4 13
3 11
3 12
6
10 15
13 12
2 15
8 4
15 12
6 13

*/
时间: 2024-10-10 22:54:28

繁华模拟赛 约会的相关文章

[繁华模拟赛]Evensgn 剪树枝

Evensgn 剪树枝 题目 繁华中学有一棵苹果树.苹果树有 n 个节点(也就是苹果),n − 1 条边(也就 是树枝).调皮的 Evensgn 爬到苹果树上.他发现这棵苹果树上的苹果有两种:一 种是黑苹果,一种是红苹果.Evensgn 想要剪掉 k 条树枝,将整棵树分成 k + 1 个 部分.他想要保证每个部分里面有且仅有一个黑苹果.请问他一共有多少种剪树枝 的方案? INPUT 第一行一个数字 n,表示苹果树的节点(苹果)个数. 第二行一共 n − 1 个数字 p0, p1, p2, p3,

繁华模拟赛 Evensgn的债务

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll int using namespace std; const int maxn = 1000005; ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(

繁华模拟赛 ljw分雕塑

/* 用f[i][k]表示考虑到第i个雕塑,分成k组,可不可行(这是一个bool类型的数组) 转移: f[i][k]=f[j][k-1],sum[i]-sum[j]合法 */ #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; typedef long long ll; const int max_n = 2010;

繁华模拟赛 找十字架

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int n; char s[205][205],cmd; int main(){ freopen("puzzle.in","r",stdin); freopen("puzzle

繁华模拟赛 Vincent的城堡

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll mod = 1000000007; ll n,k,c[20][20]; ll ansa,ansb,ans; void get_c(){ for(int i = 1;i

繁华模拟赛 Evensgn玩序列

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5000; int n,a[maxn],b[maxn],c[maxn],rka[maxn],rkb[maxn],rkc[maxn]; bool visa[maxn],visb[maxn],vi

繁华模拟赛 ljw搭积木

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; const int maxn = 6005; int n,x[maxn]; int cmd,cnt,ans,max_x; int main(){ freopen("box.in","r"

繁华模拟赛 Vicent坐电梯

/*n<=5000­这样就不能用O(n)的转移了,而是要用O(1)的转移.­注意我们每次的转移都来自一个连续的区间,而且我们是求和­区间求和?­前缀和!­令sum[step][i]表示f[step][1~i]的和­还是以B下侧为例­ f[step][i]=sum[step-1][i-1]+sum[step-1][k]-sum[step-1][i] */#include <cstdio> #include <cstring> #include <cstdlib> #

繁华模拟赛 Evensgn剪树枝

#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int maxn = 100005; const ll mod = 1000000007; struct edge{ int t