2013 icpc 长春(5.5)

本文提供了多项编程竞赛题目的解析及代码实现,涵盖了字符串处理、数据结构、算法优化等多个方面,适合算法竞赛选手及编程爱好者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A - Hard Code

题目链接:https://vjudge.net/contest/226594#problem/A

题意

给你n, m, 把给你的字符串按顺序分成n个长度为m的字符串, 并按顺序输出

题解

签到题

#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define fi first
#define se second
#define fio ios::sync_with_stdio(false);cin.tie(0)

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pii;

const int INF = 0x3f3f3f3f;
const int M = 100005;
const int MOD = 1e9 + 7;
const double pi = acos(-1);

char s[1005];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n, m;
        string tp;
        scanf("%d %d %s", &n, &m, s + 1);
        for(int i = 1; i <= n * m; ++i)
        {
            tp += s[i];
            if(i % m == 0)
            {
                cout << tp << endl;
                tp = "";
            }
        }
    }
    return 0;
}

B - Golden Radio Base

题目链接:https://vjudge.net/contest/226594#problem/B

题意

输入一个十进制数,输出它的ϕ进制数(ϕ = (1+√5)/2)
题目给了两个关于ϕ进制数的提示
1.ϕ + 1 = ϕ^2
2. 2 ∗ ϕ^2 = ϕ^3 + 1

题解

从第一个公式得 ϕ^n + ϕ^(n-1) = ϕ^(n+1)
所以可以知道比如10(ϕ) + 1(ϕ) = 11(ϕ) => 100(ϕ)
对于11(ϕ) 一定要转化成 100(ϕ)
从第二个公式地 2 × ϕ^n = ϕ^(n + 1) + ϕ^(n - 2)
即对于1(ϕ) + 1(ϕ) = 10.01(ϕ)
知道了这些,我们就能模拟ϕ进制数的加法了
我们大胆猜测1e9的数在ϕ进制下不会超过100位,那么直接模拟就不会超时

#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define fi first
#define se second
#define fio ios::sync_with_stdio(false);cin.tie(0)

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pii;

const int INF = 0x3f3f3f3f;
const int M = 100005;
const int MOD = 1e9 + 7;
const double pi = acos(-1);

int n, ans[210], b[35][210];

void change11(int* a, int x);

void change2(int* a, int x)
{
    a[x] = 0;
    if(a[x + 2]) change2(a, x + 2);
    else
    {
        a[x + 2] = 1;
        if(a[x + 3]) change11(a, x + 2);
        //if(a[x + 1]) change11(a, x + 1);
    }
    if(a[x - 1]) change2(a, x - 1);
    else a[x - 1] = 1;
}

void change11(int* a, int x)
{

    a[x + 1] = 0;
    a[x] = 0;
    if(a[x - 1]) change2(a, x - 1);
    else a[x - 1] = 1;
}

void add(int* a, int* b)
{
    for(int i = 101; i <= 200; ++i)
    {
        if(a[i] && b[i]) change2(a, i);
        else if(!a[i] && b[i]) a[i] = 1;
    }
    for(int i = 100; i >= 0; --i)
    {
        if(a[i] && b[i]) change2(a, i);
        else if(!a[i] && b[i]) a[i] = 1;
    }
    for(int i = 199; i >= 0; --i)
        if(a[i] && a[i + 1]) change11(a, i);
}

void init()
{

    b[0][100] = 1;
    for(int i = 1; i <= 31; ++i)
    {
        add(b[i], b[i - 1]);
        add(b[i], b[i - 1]);
    }
}

int main()
{
    init();
    while(~scanf("%d", &n))
    {
        memset(ans, 0, sizeof(ans));
        for(int i = 0; i <= 31; ++i)
        {
            if((n >> i) & 1) add(ans, b[i]);
        }
        int q = 0, ed = 200;
        for(int i = 0; i <= 200; ++i)
        {
            if(ans[i])
            {
                q = i;
                break;
            }
        }
        for(int i = 200; i >= 0; --i)
        {
            if(ans[i])
            {
                ed = i;
                break;
            }
        }
        for(int i = q; i <= ed; ++i)
        {
            printf("%d", ans[i]);
            if(i == 100 && i != ed) printf(".");
        }
        puts("");
    }
    return 0;
}

C - Little Tiger vs. Deep Monkey

题目链接:https://vjudge.net/contest/226594#problem/C

题解

简单01背包

#include<bits/stdc++.h>
using namespace std;

const int  M = 40010;
int n, a[50], t;
long long vis[M];
double p;
int main() {
    cin>>t;
    while (t--) {
        memset(vis, 0, sizeof(vis));
        cin>>n>>p;
        for (int i = 0; i < n; i++)
            scanf("%d", a + i);
        vis[0] = 1;
        for (int i = 0; i < n; i++)
        for (int j = M; j >= 0; j--) if (j >= a[i]) vis[j] += vis[j - a[i]];
        long long sum = 0;
        for (int i = 0; i < M; i++) {
            sum += vis[i];
            if (sum * 1.0 / (1ll << n) >= p) {
                printf("%d\n", i);
                break;
            }
        }
    }
}

D - Bathysphere

题目链接:https://vjudge.net/contest/226594#problem/D

题解:很显然,两端是一个和x有关的二次函数,那么只需要采取双指针的方式,控制两端之间的距离刚好等于 2d 2 d 就行了

坑点:

1.由于数字比较大,达到了1e9,所以在计算二次函数的最值得时候就会出问题(1e18 > 16 后几位的精度都会炸),而三分时间又会炸,所以要用long double, 而二次函数单独写一个结构体是一个比较好的处理方式。

2.身为一个要输出浮点数的几何题居然没有SPJ,不老老实实保留三位小数会wa的亲妈都不认识。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;

long double eps = 1e-9;
int sign(long double x) {
    if (fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}
struct point {
    long double x, y;
    point(long double x = 0, long double y = 0): x(x), y(y) {}
    void read() {
        double tmpx, tmpy;
        scanf("%lf%lf", &tmpx, &tmpy);
        x = tmpx;
        y = tmpy;
    }
}p[N];

struct pow2fuction {
    long double a, b, c;
    pow2fuction(long double a = 0, long double b = 0, long double c = 0) :a(a), b(b), c(c) { }
    long double val(long double x) {
        return a * x * x + b * x + c;
    }
    pow2fuction operator - (const pow2fuction &rhs) const {
        return pow2fuction(a - rhs.a, b - rhs.b, c - rhs.c);
    }
    long double mx(long double l, long double r) {
        long double ret = this->val(l);
        ret = max(ret, this->val(r));
        long double tmp = -b / (2 * a);
        if (a < 0 && l < tmp && tmp < r) ret = max(ret, this->val(tmp));
        return ret;
    }
};
pow2fuction cal(int pos, long double v) {
    long double k = (p[pos + 1].y - p[pos].y) / (p[pos + 1].x - p[pos].x);
    long double m = p[pos].y - p[pos].x * k;
    long double tmp1 = m + p[pos].y + k * v;
    long double tmp2 = v - p[pos].x;
    return pow2fuction(k / 2, (tmp1 + k * tmp2) / 2, tmp1 * tmp2 / 2);
}
long double area(int pos) {return (p[pos].y + p[pos + 1].y) * (p[pos + 1].x - p[pos].x) * 0.5;}
int n, l, d, t;
int main() {
    scanf("%d", &t);
    while (t--) {
        long double ans = 0, now = 0;
        scanf("%d%d", &n, &l);
        for (int i = 1; i <= n; i++) p[i].read();
        scanf("%d", &d);
        if (sign(d == 0)) {
            for (int i = 1; i <= n; i++) ans = max(ans, p[i].x);
            printf("%.3f\n", (double)ans);
            continue;
        }
        d <<= 1;
        int l = 1, r = 1;
        long double nowx = 0;
        while (p[r + 1].x - p[l].x  < d && r + 1 <= n) now += area(r++);
        if (r == n) ans = now;
        while (r < n) {
            long double limit = min(p[l + 1].x - nowx, p[r + 1].x - (nowx + d));
            ans = max(ans, now + (cal(r, d) - cal(l, 0)).mx(nowx, nowx + limit));
            nowx += limit;
            if (sign(nowx - p[l + 1].x) == 0)  now -= area(l++);
            if (sign(nowx + d - p[r + 1].x) == 0)  now += area(r++);
        }
        printf("%.3f\n", (double)ans / d);
    }
}

E - Min-max-multiply

题目链接:https://vjudge.net/contest/226594#problem/E

F - RP problem

题目链接:https://vjudge.net/contest/226594#problem/F

题解

设每一个人的价值为x,这样我们可以得到n个方程,在不考虑加边的情况下.我们可以直接高斯消元得到分配方案或者可以判断出是否有多解, 那么现在来考虑加边的情况,我们可以发现加上一条边只会影响其中的一列,那么我们就可以在矩阵后面加上m列每一列为加上一条边的情况,然后就可以愉快的高斯消元了.

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
const int M = 3e6 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline LL mm(LL x, LL p){return x >= p ? x - p : x < 0 ? x + p : x;}

struct Matrix{
    int n, m, u, v;
    vector<int>son[105];
    double a[105][210];
    double exp = 1e-9;
    bool vis[105][105];
    bool use[105];
    int id[210];
    bool flag = true;
    void solve(){
        read();
        if(!Guass()){
            puts("INF");
            return ;
        }
        int ans = -1;
        double now = a[n - 1][m];
        for(int i = n; i < m; ++i){
            if(a[n - 1][m] / a[n - 1][i] > now){
                ans = id[i];
                now = a[n - 1][m] / a[n - 1][i];
            }
        }
        printf("%d %d\n", 1, ans);
    }
    void read(){
        memset(a, 0, sizeof a);
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; ++i)  son[i].clear();
        memset(vis, false, sizeof vis);
        for(int i = 1; i <= m; ++i){
            scanf("%d%d", &u, &v);
            if(u == v)  continue;
            if(!vis[u][v]) son[u].push_back(v), vis[u][v] = true;
        }
        for(int i = 0; i < n; ++i){
            a[i][i] = -1.0;
            for(int j = 0; j < son[i].size(); ++j){
                u = son[i][j];
                a[u][i] = 1.0 / (son[i].size());
            }
        }
        for(int i = 0; i < n; ++i)  a[n - 1][i] = 1.0;
        memset(use, false, sizeof use);
        for(int i = 0; i < son[n - 1].size(); ++i)  use[son[n - 1][i]] = true;
        m = n;
        for(int i = 0; i < n - 1; ++i){
            if(!use[i]){
                a[i][m] = 1.0 / (son[n - 1].size() + 1);
                for(auto it : son[n - 1])   a[it][m] = 1.0 / (son[n - 1].size() + 1);
                a[n - 1][m] = 1;
                id[m] = i;
                ++m;
            }
        }
        a[n - 1][m] = 1.0;
       // pri();
    }
    void swap_line(int x, int y){
        for(int j = 0; j <= m; ++j) swap(a[x][j], a[y][j]);
    }
    void pri(){
        for(int i = 0; i < n; ++i)  for(int j = 0; j <= m; ++j) printf("%.6f%c", a[i][j], " \n"[j == m]);

        for(int i = 0; i <= m; ++i) printf("%d%c", id[i], " \n"[i == m]);
    }
    bool Guass(){
       // printf("%d %d\n", n, m);
        for(int j = 0; j < n; ++j){
            int r = j;
            for(int i = j + 1; i < n; ++i) if(fabs(a[i][j]) > fabs(a[r][j]))   r = i;
            if(fabs(a[r][j]) < exp) return 0;
            if(r != j)  swap_line(r, j);
            for(int i = j + 1; i <= m; ++i) a[j][i] /= a[j][j];
            a[j][j] = 1.0;
            for(int i = j + 1; i < n; ++i){
                double l = a[i][j];//if(i == 13 && j == 0)    printf("%.9f %.9f\n", l, a[i][j]);
                if(fabs(l) < exp) continue;
                for(int k = j; k <= m; ++k){
                 //   if(i == 13 && k == 0)   printf("%.9f, %.9f, %.9f\n", a[i][k], l, a[j][k]);
                    a[i][k] -= l * a[j][k];
                }
            }
        }
       // pri();
     //  for(int i = 0; i < n; ++i)  for(int j = 0; j < i; ++j) if(fabs(a[i][j]) > exp) printf("----%d %d %.9f\n", i, j, a[i][j]);
        return true;
    }
}mmm;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        mmm.solve();
    }
    return 0;
}

G - Mosaic

题目链接:https://vjudge.net/contest/226594#problem/G

题解:一个矩阵,然后询问其中子矩阵内的最大值,最小值,并用这两个数的平均数去更新子矩阵的中心。二维线段树的板子题,写的时候注意点是在外面那层线段树的push_up上

1.在build的时候,需要将当前节点对应的整棵线段树都push_up了

2.在update的时候,只需要将对当前这棵树所涉及到的那条链push_up了

#include<bits/stdc++.h>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;

const int N = 805;
int n, T, q, x, y, l, icase;
struct seg_tree {
    int treema[N << 2], treemi[N << 2];
    void build(int l, int r, int rt) {
        if (l == r) {
            scanf("%d", &treema[rt]);
            treemi[rt] = treema[rt];
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        treema[rt] = max(treema[rt << 1], treema[rt << 1 | 1]);
        treemi[rt] = min(treemi[rt << 1], treemi[rt << 1 | 1]);
    }
    void update(int l, int r, int rt, int k, int val) {
        if (l == r) {
            treema[rt] = treemi[rt] = val;
            return;
        }
        int mid = (l + r) >> 1;
        if (k <= mid) update(lson, k, val);
        else update(rson, k, val);
        treema[rt] = max(treema[rt << 1], treema[rt << 1 | 1]);
        treemi[rt] = min(treemi[rt << 1], treemi[rt << 1 | 1]);
    }
    int query(int l, int r, int rt, int L, int R, int op) {
        if (r < L || R < l) {
            if (op == 1) return 0;
            else return (int)2e9;
        }
        if (L <= l && r <= R) {
            if (op == 1) return treema[rt];
            else return treemi[rt];
        }
        int mid = (l + r) >> 1;
        if (op == 1) return max(query(lson, L, R, op), query(rson, L, R, op));
        else return min(query(lson, L, R, op), query(rson, L, R, op));
    }
};

seg_tree sst[N << 2];
void push_up(int l, int r, int rt, int xid) {
    sst[xid].treema[rt] = max(sst[xid << 1].treema[rt], sst[xid << 1 | 1].treema[rt]);
    sst[xid].treemi[rt] = min(sst[xid << 1].treemi[rt], sst[xid << 1 | 1].treemi[rt]);
    if (l == r) return;
    int mid = (l + r) >> 1;
    push_up(lson, xid);
    push_up(rson, xid);
}

void build(int l, int r, int rt) {
    if (l == r) {
        sst[rt].build(1, n, 1);
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    push_up(1, n, 1, rt);
}
void push_up(int l, int r, int rt, int xid, int pos) {
    sst[xid].treema[rt] = max(sst[xid << 1].treema[rt], sst[xid << 1 | 1].treema[rt]);
    sst[xid].treemi[rt] = min(sst[xid << 1].treemi[rt], sst[xid << 1 | 1].treemi[rt]);
    if (l == r) return;
    int mid = (l + r) >> 1;
    if(pos <= mid)push_up(lson, xid, pos);
    else push_up(rson, xid, pos);
}
void update(int l, int r, int rt, int xpos, int ypos, int val) {
    if (l == r) {
        sst[rt].update(1, n, 1, ypos, val);
        return;
    }
    int mid = (l + r) >> 1;
    if (xpos <= mid) update(lson, xpos, ypos, val);
    else update(rson, xpos, ypos, val);
    push_up(1, n, 1, rt, ypos);
}
int query(int l, int r, int rt, int xl, int xr, int yl, int yr, int op) {
    if (xr < l || r < xl) {
        if (op == 1) return 0;
        else return (int)2e9;
    }
    if (xl <= l && r <= xr) {
        return sst[rt].query(1, n, 1, yl, yr, op);
    }
    int mid = (l + r) >> 1;
    if (op == 1) return max(query(lson, xl, xr, yl, yr, op), query(rson, xl, xr, yl, yr, op));
    else return min(query(lson, xl, xr, yl, yr, op), query(rson, xl, xr, yl, yr, op));
}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        build(1, n, 1);
        printf("Case #%d:\n", ++icase);

        scanf("%d", &q);
        while(q--) {
            scanf("%d%d%d", &x, &y, &l);
            int sz = l >> 1;
            int num1 = query(1, n, 1, max(x - sz, 1), min(x + sz, n), max(y - sz, 1), min(y + sz, n), 1);
            int num2 = query(1, n, 1, max(x - sz, 1), min(x + sz, n), max(y - sz, 1), min(y + sz, n), 2);
            printf("%d\n", (num1 + num2) / 2);
            update(1, n, 1, x, y, (num1 + num2) / 2);
        }
    }
}

H - Tower

题目链接:https://vjudge.net/contest/226594#problem/H

I - String

题目链接:https://vjudge.net/contest/226594#problem/I

题解

字符串hash, 然后暴力的枚举每一个结束位置,用一个map去存当前长度为l的串是否出现过,如果出现过那么从前面开始删, 这样每一个串只会被丢进去一次删除一次.

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 3e5 + 10;
const int M = 3e6 + 10;
const LL mod = 998244353;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}

char s[N];
uLL base = 233;
uLL ba[N];
uLL ha[N];
void init(int len){
    ha[0] = 1;
    for(int i = 1; i <= len; ++i)   ha[i] = ha[i - 1] * base + s[i] - 'a';
    ba[0] = 1;
    for(int i = 1; i <= len; ++i) ba[i] = ba[i - 1] * base;
}
uLL get_ha(int x, int l, int len){
    return ha[l + x - 1] - ha[x - 1] * ba[l];
}
map<uLL, int>mp;
int solve(int x, int len, int m, int l){
    if(m == 1)  return (len - x + 1) / l;
    int res = 0, tot = 0;
    mp.clear();
    for(int i = x, j = x; i + l - 1 <= len; i += l){
        uLL now = get_ha(i, l, len);
        while(mp[now]){
            uLL gg = get_ha(j, l, len);
            mp[gg]--;
            tot--;
            j += l;
        }
        tot++;
        mp[now]++;
        if(tot >= m)    res++;
    }
    return res;
}
int main(){
    int m, l;
    while(~scanf("%d%d", &m, &l)){
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        init(len);
        int ans = 0;
        for(int i = 1; i <= l; ++i){
            ans += solve(i, len, m, l);
        }
        printf("%d\n", ans);
    }
    return 0;
}

J - Tri-war

题目链接:https://vjudge.net/contest/226594#problem/J

题解

倍增的求lca,然后就是分类讨论,暴力的求出每一个点的影响范围.

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, LL> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 3e6 + 10;
const LL mod = 998244353;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}

int n;
int deep[N], fa[20][N], si[N];
vector<int>vc[N];
void dfs(int o, int u){
    fa[0][o] = u;
    for(int i = 1; i <= 19; ++i)    fa[i][o] = fa[i - 1][fa[i - 1][o]];
    deep[o] = deep[u] + 1;
    si[o] = 1;
    for(auto it : vc[o])   if(it != u)  dfs(it, o), si[o] += si[it];
}
int get_lca(int x, int y){
    if(deep[x] < deep[y])   swap(x, y);
    int dd = deep[x] - deep[y];
    for(int i = 0; dd; dd >>= 1, ++i)   if(dd & 1)  x = fa[i][x];
    if(x == y)  return y;
    for(int i = 19; i >= 0; --i)    if(fa[i][x] != fa[i][y])    x = fa[i][x], y = fa[i][y];
    return fa[0][x];
}
int up(int x, int dd){
    for(int i = 0; dd; dd >>= 1, ++i)   if(dd & 1)  x = fa[i][x];
    return x;
}
int solve(int x, int y, int z){
    int lca1 = get_lca(x, y), lca2 = get_lca(x, z);
    int len1 = deep[x] + deep[y] - 2 * deep[lca1];
    int len2 = deep[x] + deep[z] - 2 * deep[lca2];
    bool flag1 = false, flag2 = false;
    if(((len1 - 1) >> 1) < deep[x] - deep[lca1] && x != lca1) flag1 = true;
    if(((len2 - 1) >> 1) < deep[x] - deep[lca2] && x != lca2) flag2 = true;
    if(flag1 && flag2){
        int len = min((len1 - 1) >> 1, (len2 - 1) >> 1);
        return si[up(x, len)];
    }
    else if(flag1 || flag2){
        if(flag2){
            swap(y, z);
            swap(lca1, lca2);
            swap(len1, len2);
        }
        int to = up(x, (len1 - 1) >> 1);
        int res = si[to];
        if(deep[lca2] >= deep[to])
            res -= si[up(z, (len2 >> 1))];
        return res;
    }
    else{
        int lca3 = get_lca(y, z);
        int to1 = up(y, len1 >> 1), to2 = up(z, len2 >> 1);
        if(deep[to1] <= deep[lca3] || deep[to2] <= deep[lca3])  return n - max(si[to1], si[to2]);
        else    return n - si[to1] - si[to2];
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--){
        int u, v;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) vc[i].clear();
        for(int i = 1; i < n; ++i){
            scanf("%d%d", &u, &v);
            vc[u].push_back(v);
            vc[v].push_back(u);
        }
        dfs(1, 1);
        int q, x, y, z;
        scanf("%d", &q);
        while(q--){
            scanf("%d%d%d", &x, &y, &z);
            printf("%d %d %d\n", solve(x, y, z), solve(y, x, z), solve(z, x, y));
        }
    }

    return 0;
}
/*
1
9
1 2
1 3
1 4
2 5
2 6
2 7
6 8
6 9
4
6 3 9
8 9 6
8 9 3
8 4 7
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值