这次比赛的题目总体来讲比较水 因为我都做出了4个题 = =。
A B C题
这三个题没什么可说的太简单了= =。
D题
利用前缀和的思想,先预处理所有的前缀和,然后看开头字母相同的有没有前缀和相同的 有就是一个答案。需要注意 题目中会出现long long作下标的情况,因此要使用map
E题
这是一个LCA的应用,由于所求涉及到割级祖先,使用在线倍增算法求解。
#pragma comment (linker, "/STACK:1024000000, 1024000000")
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 100010;
int n,m;
int tot, head[MAX];
int deep[MAX],father[MAX],size[MAX],p[MAX][20];
struct edge{
int v,next;
}node[MAX << 1];
void init(){
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v){
node[tot].v = v;
node[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u, int pre, int t){
size[u] = 1;//记录以u为根的结点有多少个
deep[u] = t;//记录深度
father[u] = pre;//记录父亲
for(int i=head[u]; i!=-1; i=node[i].next){
int v = node[i].v;
if(v != pre){
dfs(v, u, t+1);
size[u] += size[v];
}
}
}
void make_parent(){//预处理各级祖先 也是倍增的体现
for(int i=1; i<=n; i++) p[i][0] = father[i];
for(int j=1; (1<<j)<=n; j++)
for(int i=1; i<=n; i++)
p[i][j] = p[p[i][j-1]][j-1];
}
int make_ancestor(int u, int dif){//求解跳到哪个祖先处
int ret = u;
for(int i=0; i<20; i++)
if(dif & (1 << i)) ret = p[ret][i];
return ret;
}
int lca(int a, int b){//求解LCA过程
if(deep[a] < deep[b]) swap(a, b);
for(int j=19; j>=0; j--)
if(deep[a] - (1 << j) >= deep[b])
a = p[a][j];
if(a == b) return a;
for(int j=19; j>=0; j--){
if(p[a][j] != p[b][j]){
a = p[a][j];
b = p[b][j];
}
}
return p[a][0];
}
int query(int a, int b){
if(a == b) return n;//注意如果是同一个点,那么所有点都满足要求,直接返回
if(deep[a] < deep[b]) swap(a, b);
int c = lca(a, b);
int da = deep[a] - deep[c];
int db = deep[b] - deep[c];
int sum = da + db;
if(sum & 1) return 0;//因为从a到b一定会经过它们的lca,因此如果路程是奇数,一定不存在满足条件的点
if(deep[a] == deep[b]){//如果所求两个点深度相同,它们到lca的距离必然相同
int fa = make_ancestor(a, da - 1);//a跳到lca的最近的子节点
int fb = make_ancestor(b, db - 1);//b也跳到lca的最近的字节点
return n - size[fa] - size[fb];//那么答案就是所有结点中除掉以fa,fb为根节点的结点的数量
}
else{//如果深度不同的话
sum >>= 1;//找到a到b路径上的中点,它是一个满足条件的点,同时它不在路径上的其他子结点以及子树上的点都是符合条件的
int dx = make_ancestor(a, sum);
int dy = make_ancestor(a, sum - 1);
return size[dx] - size[dy];
}
}
int main(){
scanf("%d",&n);
init();
for(int i=0; i<n-1; i++){
int u, v;
scanf("%d%d",&u,&v);
addedge(u, v);
addedge(v, u);
}
scanf("%d",&m);
dfs(1, 0, 0);
make_parent();
for(int i=0; i<m; i++){
int u, v;
scanf("%d%d",&u,&v);
printf("%d\n",query(u, v));
}
return 0;
}