ACM模版
描述
题解
第一次接触主席树,感觉好叼好叼,无法驾驭它啊~~~
贴一下官方题解吧:
貌似,这里用树状数组维护也是可以的啊……当然,我并不会。水平太臭了!
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN =
1e5 +
10;
const int MAXM =
2e6 +
10;
int n, tot, sz;
int LS[MAXN], RS[MAXN];
int LE[MAXN], RE[MAXN];
int tmp[MAXN];
int pos[MAXN];
int vis[MAXN];
int head[MAXN];
int root[MAXN];
struct node
{
int l, r, c;
} tree[MAXM];
struct Edge
{
int to, nt;
} e[MAXN];
void init()
{
tot =
0;
memset(head, -
1,
sizeof(head));
memset(vis,
0,
sizeof(vis));
}
void addedge(
int u,
int v)
{
e[tot].to = v;
e[tot].nt = head[u];
head[u] = tot++;
}
void dfs(
int u,
int pre,
int flag)
{
if (flag)
{
RS[u] = ++sz;
tmp[sz] = pos[u];
}
else
{
LS[u] = ++sz;
pos[u] = sz;
}
int v;
for (
int i = head[u]; i != -
1; i = e[i].nt)
{
v = e[i].to;
if (v != pre)
{
dfs(v, u, flag);
}
}
if (flag)
{
RE[u] = sz;
}
else
{
LE[u] = sz;
}
}
template <
class T>
inline void scan_d(T &ret)
{
char c;
ret =
0;
while ((c = getchar()) <
'0' || c >
'9');
while (c >=
'0' && c <=
'9')
{
ret = ret *
10 + (c -
'0'), c = getchar();
}
}
void update(
int &rt,
int l,
int r,
int num)
{
tree[++sz] = tree[rt];
rt = sz;
tree[rt].c++;
if (l == r)
{
return ;
}
int mid = (l + r) >>
1;
if (num <= mid)
{
update(tree[rt].l, l, mid, num);
}
else
{
update(tree[rt].r, mid +
1, r, num);
}
}
int query(
int x,
int y,
int L,
int R,
int l,
int r)
{
if (L <= l && R >= r)
{
return tree[y].c - tree[x].c;
}
int m = (l + r) >>
1;
int ret =
0;
if (L <= m)
{
ret += query(tree[x].l, tree[y].l, L, R, l, m);
}
if (R > m)
{
ret += query(tree[x].r, tree[y].r, L, R, m +
1, r);
}
return ret;
}
int main()
{
scan_d(n);
int u, v, r =
0;
init();
for (
int i =
1; i < n; i++)
{
scan_d(u), scan_d(v);
addedge(u, v);
vis[v] =
1;
}
sz =
0;
for (
int i =
1; i <= n; i++)
{
if (vis[i] ==
0)
{
r = i;
break;
}
}
dfs(r,
0,
0);
init();
for (
int i =
1; i < n; i++)
{
scan_d(u), scan_d(v);
addedge(u, v);
vis[v] =
1;
}
sz =
0;
for (
int i =
1; i <= n; i++)
{
if (vis[i] ==
0)
{
r = i;
break;
}
}
dfs(r,
0,
1);
root[
0] =
0, sz =
0;
for (
int i =
1; i <= n; i++)
{
root[i] = root[i -
1];
update(root[i],
1, n, tmp[i]);
}
long long ans =
0;
for (
int i =
1; i <= n; i++)
{
int x = query(root[RS[i] -
1], root[RE[i]], LS[i], LE[i],
1, n);
ans +=
1LL * (x -
1) * (x -
2) /
2;
}
printf(
"%lld\n",ans);
return 0;
}
参考
《主席树》