lca加训

CF519E

#include<bits/stdc++.h>
#define fi first
#define se second
#define log2(a) log(n)/log(2)
#define show(a) cout << a << endl;
#define show2(a,b) cout << a << ' ' << b << endl;
#define show3(a,b,c) cout << a << ' ' << b << ' ' << c << endl;
#define int long long
#define endl '\n'

using namespace std;

void fileio()
{
  //#ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  //#endif
}

void fileclose()
{
    fclose(stdin);//关闭文件
    fclose(stdout);//关闭文件
}

using namespace std;

const int N = 1e5 + 10;
vector<int> g[N];
int n;
int m;

int d[N]; int t;
int f[N][20];
queue<int>q;

int siz[N];

void bfs()
{
    d[1] = 1;
    q.push(1);
    while(q.size())
    {
      int x = q.front();q.pop();
      for(auto i : g[x])
      {
        if(d[i])continue;
        d[i] = d[x] + 1;
        f[i][0] = x;
        for(int j = 1;j <= t;j ++) f[i][j] = f[f[i][j-1]][j-1];
        q.push(i);
      }
    }
}

void dfs(int x,int fa)
{
    siz[x] = 1;
    for(int y : g[x])
    {
        if(y == fa) continue;
        dfs(y,x);
        siz[x] += siz[y];
    }
}

int lca(int x,int y)
{
    if(d[x] > d[y]) swap(x,y);  // 保证x浅
    for(int i = t;i >= 0;i --) if(d[f[y][i]] >= d[x]) y = f[y][i];
    if(x==y) return x;
    for(int i = t;i >= 0;i --) if(f[x][i] != f[y][i])
    x = f[x][i] , y = f[y][i];
    return f[x][0];
}

int query(int x,int y)
{
    return d[x] + d[y] - 2 * d[lca(x,y)];
}

int findmid(int x,int y)
{
    if(query(x,y) & 1) return 0;
    
    if(d[x] == d[y]){ for(int i = t;i >= 0;i --) if(f[x][i]!=f[y][i])
    x = f[x][i],y = f[y][i]; return n - siz[x] - siz[y];
    }
    if(d[x]>d[y]) swap(x,y); // 保证 x 浅
    int mid = d[y] - (query(x,y)>>1);
    for(int i = t;i >= 0;i --) if(d[f[y][i]] > mid) y = f[y][i];
    return siz[f[y][0]] - siz[y];

}

void solve()
{ 
   cin >> n; t = (log(n)/log(2)) + 1;
   for(int i = 1;i < n;i ++)
   {
       int x,y;cin >> x >> y;
       g[x].push_back(y);
       g[y].push_back(x);
   }
   bfs();
   dfs(1,0);
   cin >> m;
   for(int i = 0;i < m;i ++)
   {
     int x,y;
     cin >> x >> y;
     if(x==y) cout << n << endl;
     else cout << findmid(x,y) << endl;
   }

}
 
signed main()
{ 
    //fileio();
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);int T = 1;
    //cin >> T;
    while(T --) solve();
    //fileclose();
}

P3128

树上点差分的模板题

#include<bits/stdc++.h>
#include<iostream>
#define fi first
#define se second
#define log2(a) log(n)/log(2)
#define show(a) cout << a << endl;
#define show2(a,b) cout << a << ' ' << b << endl;
#define show3(a,b,c) cout << a << ' ' << b << ' ' << c << endl;
#define int long long
#define endl '\n'
#define debug cout << "debug" << endl

using namespace std;

void fileio()
{
  //#ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  //#endif
}

void fileclose()
{
    fclose(stdin);//关闭文件
    fclose(stdout);//关闭文件
}

using namespace std;

int n,k;
const int N = 1e5 + 10;
vector<int> g[N];
int d[N];
int f[N][20];
int cnt[N];
int t;


void bfs(){
    queue<int> q;
    q.push(1); d[1] = 1; 
    while(q.size())
    {
        int x = q.front(); q.pop();
        for(auto y : g[x])
        {
            if(d[y]) continue;
            d[y] = d[x] + 1; f[y][0] = x;
            for(int j = 1;j <= t;j ++)
            f[y][j] = f[f[y][j-1]][j-1];
            q.push(y);
        }
    }
}

int lca(int x,int y)
{
    if(d[x] > d[y] ) swap(x,y);
    for(int i = t;i >= 0;i --) if(d[f[y][i]] >= d[x]) y = f[y][i];
    if(x == y) return x;
    for(int i = t;i >= 0;i --) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    return f[x][0];
}

void dfs(int x,int fa){

    for(int y : g[x])
    {
        if(y == fa) continue;
        dfs(y,x);
        cnt[x] += cnt[y];
    }
}

void solve()
{  
    //debug;
    cin >> n >> k;
    t = log2(n) + 1;

   for(int i = 1;i < n;i ++)
   {
     int a,b;cin >> a >> b;
     g[a].push_back(b); g[b].push_back(a);
   } 
  
   bfs(); 
   while(k --)
   {
      int u,v; cin >> u >> v;
      cnt[u] ++,cnt[v] ++;
      cnt[lca(u,v)] --; cnt[f[lca(u,v)][0]] --;
   } 
 
   dfs(1,0);
   int res = -1;
   for(int i = 1;i <= n;i ++) res = max(res,cnt[i]);
  
   cout << res << endl;

}
 
signed main()
{ 
    //fileio();
    //debug;
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);int T = 1;
    //cin >> T;
    while(T --) solve();
    //fileclose();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值