题目大意:给定一棵树和树上的m条路径,求这m条路径中任选两条不同的路径时其中一条包含另一条的概率是多少
这题还真是精神污染- -
首先一个显而易见的结论就是如果路径A包含于路径B 那么就有A的两端点在路径B上 这是个充要条件
于是我们对于每个A路径的两段点x和y,将x开一个vector,把y存进去
这样对于每个B路径 我们要找的就是B路径上的所有点在vector中有多少出边也在这条B路径上
有些拗口- -
那么我们可以维护树上主席树来确定B链对应的线段树
我们要确定的就是B链对应的线段树中有多少点在B链上
那么维护入栈出栈序就可以了
将每个点维护一个可持久化线段树 版本是父亲版本加上该节点的vector中所有元素在入栈出栈序上的位置
由于是入栈出栈序 因此入栈为1 出栈为-1
由于入栈出栈序只能查询一个节点指向根的一条链 因此我们将[x,y]这条链拆成[x,lca]和[lca,y]两段
这其中由于lca被算了两次 因此还要减掉[lca,lca] 就可以了
注意自己对自己的影响不计入答案
- -卡内存差评
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct Segtree{
Segtree *ls,*rs;
int val;
void* operator new (size_t,Segtree *_,Segtree *__,int ___)
{
static Segtree mempool[3804000],*C=mempool;
C->ls=_;
C->rs&#