這次比賽的題目總體來講比較水 因爲我都做出了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;
}