羅馬種了一棵樹,樹上有n個點。每個點有乙個小寫英文本母。1號點是樹的根,剩下的n-1個點都有乙個父親。點和父親之間通過乙個邊相連。第i個點的父親是pi,且pi乙個點的深度是從根到當前點的路徑上經過的點數。根的深度是1。
u在v的子樹中,當且僅當u往根方向走可以到達v。特別的,v也是在v的子樹中。
羅馬給你m個查詢,第i個查詢包含兩個整數vi,hi。現在收集在vi子樹中且深度是hi的結點。判斷一下把這些結點重新排列是否能組成乙個回文。
樣例解釋:
乙個字串s是回文,當且僅當他正著讀和反著讀是一樣的。空串也是回文。
第一查詢中,點1包含z,可以構成回文。
第二個查詢中點5和6包含c,d,這個不能組成回文。
第三個查詢中,沒有點是深度4的,組成乙個空串。
第四個查詢中,也是構成了乙個空串。
第五個查詢中,2,3,4符合查詢條件,包含字母a,c,c。可以構成cac。
input
單組測試資料。input示例第一行包含兩個n, m (1≤n,m≤500000),表示樹的結點數目和查詢數目。
第二行有n-1個數字 p2,p3,...,pn ,表示每乙個點的父親。(1≤pioutput
對於每乙個查詢,如果能夠組成回文,輸出yes,否則輸出no。
6 5output示例1 1 1 3 3
zacccd
1 13 3
4 16 1
1 2
yesyesnoyes
yes
#include #include #include #include #include using namespace std;
const int maxn = 5e5 + 10;
struct node
int index;
int height;
};int n, m;
vectorchild[maxn];
vectorbuf[maxn];
char val[maxn];
void dfs(vector&parent, int pos, int h)
for (int i = 0; i < child[pos].size(); i++)
parent.pop_back();
}char num[26];
bool valid()
}if (count > 1)
return true;
}bool cmp(const node a, const node b)
int leftmost(vector&a, int h)
else
}if (a[left].height == h)
else if (a[right].height == h)
return -1;
}int rightmost(vector&a, int h)
else
}if (a[right].height == h)
else if (a[left].height == h)
return -1;
}template inline void scan_d(t &ret)
}int main()
scanf("%s", &val[1]);
vectorparent;
dfs(parent, 1, 0);
for (int i = 1; i <= n; i++)
int v, h;
for (int i = 0; i < m; i++)
int right = rightmost(buf[v], h);
memset(num, 0, sizeof(num));
for (int j = left; j <= right; j++)
if (valid())
else
}return 0;
}
題解 yww 與樹上的回文串
題目鏈結 題意複述 給一棵樹,每條邊上有乙個字元 0 或 1 求有多少對 x,y x,滿足 x 到 y 路徑上的邊上的字元按順序組成的字串為回文串。又一道神仙題啊 用其它方法並不能方便地求出答案,考慮點分。經過乙個點的回文串只有兩種情況 先找出以重心為開頭的所有路徑所表示的字串,考慮第一種情況 可以...
BZOJ2342 雙倍回文(回文自動機 樹上差分)
題面 題意 給你乙個串,求出它的最長子串 滿足該子串有兩個長度相等且為偶數的回文串拼接而成 該串顯然是回文串,就對應回文自動機上的乙個狀態 若某個狀態的長度為4的倍數 且存在某個祖先的長度為其一半 則該狀態可以貢獻答案 因為祖先即回文字尾和字首 長度為其一半的字首和字尾都是回文串 顯然符合題意 我的...
樹上直徑 樹上最遠點O n
題目大意 對於一棵n個結點的無根樹,求出每個結點的最遠點,要求時間複雜度為o n 對於乙個點,距離它最遠的點一定是直徑的端點。證明 我們求直徑的時候,兩次dfs。兩次bfs 或者dfs 方法 先從任意一點p出發,找離它最遠的點q,再從點q出發,找離它最遠的點w,w到q的距離就是是的直徑 若p已經在直...