题目大意:给定一棵二叉树,每个结点有两个儿子或没有儿子, n n n 个叶子结点的权值为 1 1 1 到 n n n 的排列。现在我们可以任意交换某些结点的左子树和右子树,要求进行一系列交换,使得最终所有叶子节点的权值按照遍历序写出来,逆序对个数最少。 n ≤ 2 × 1 0 5 n\le 2\times 10^5 n≤2×105。
#include
typedef long long s64;
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
template <class T>
inline void relax(T &x, const T &y)
{
if (x < y)
x = y;
}
const int MaxN = 2e5 + 5;
const int MaxS = MaxN * 10;
int n, sze_seg, top, stk[MaxS];
int lc[MaxS], rc[MaxS], sze[MaxS];
s64 res1, res2, ans;
inline void del(int x)
{
lc[x] = rc[x] = sze[x] = 0;
stk[++top] = x;
}
inline int get_new()
{
return top ? stk[--top + 1]: ++sze_seg;
}
inline void insert(int &x, int l, int r, int pos)
{
if (!x) x = get_new();
++sze[x];
if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid)
insert(lc[x], l, mid, pos);
else
insert(rc[x], mid + 1, r, pos);
}
inline int merge(int x, int y, int l, int r)
{
if (!x || !y) return x + y;
res1 += 1LL * sze[lc[x]] * sze[rc[y]];
res2 += 1LL * sze[rc[x]] * sze[lc[y]];
int mid = l + r >> 1;
lc[x] = merge(lc[x], lc[y], l, mid);
rc[x] = merge(rc[x], rc[y], mid + 1, r);
return sze[x] += sze[y], del(y), x;
}
inline int solve()
{
int x;
read(x);
if (!x)
{
int ch_l = solve();
int ch_r = solve();
res1 = res2 = 0;
int res = merge(ch_l, ch_r, 1, n);
ans += std::min(res1, res2);
return res;
}
else
{
int res = 0;
insert(res, 1, n, x);
return res;
}
}
int main()
{
read(n);
solve();
std::cout << ans << std::endl;
return 0;
}
题目大意:有 N N N 座山峰,每座山峰有他的高度 h i h_i hi。有些山峰之间有双向道路相连,共 M M M 条路径,每条路径有一个困难值,这个值越大表示越难走,现在有 Q Q Q 组询问,每组询问询问从点 v v v 开始只经过困难值小于等于 x x x 的路径所能到达的山峰中第 k k k 高的山峰的高度,如果无解输出 − 1 -1 −1。允许离线。
N ≤ 1 0 5 , Q , M ≤ 5 × 1 0 5 , x , h i ≤ 1 0 9 N\le 10^5,~Q,M\le 5\times10^5,~x,h_i\le10^9 N≤105, Q,M≤5×105, x,hi≤109。
#include
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
inline void putChar(char ch)
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer;
if (ch == '\0')
fwrite(buffer, 1, head - buffer, stdout);
*head++ = ch;
if (head == tail)
fwrite(buffer, 1, buffer_size, stdout), head = buffer;
}
template <class T>
inline void putint(T x)
{
static char buf[22];
static char *tail = buf;
if (!x) return (void)(putChar('0'));
if (x < 0) x = ~x + 1, putChar('-');
for (; x; x /= 10) *++tail = x % 10 + '0';
for (; tail != buf; --tail) putChar(*tail);
}
const int MaxN = 5e5 + 5;
const int MaxS = 100001 * 18;
struct edge
{
int u, v, w;
inline void scan()
{
read(u), read(v), read(w);
}
inline bool operator < (const edge &rhs) const
{
return w < rhs.w;
}
}e[MaxN];
struct request
{
int u, x, k, num;
inline void scan(int t)
{
num = t;
read(u), read(x), read(k);
}
inline bool operator < (const request &rhs) const
{
return x < rhs.x;
}
}req[MaxN];
int n, m, Q, tot, val_num, val[MaxN], real[MaxN];
int ans[MaxN], fa[MaxN], rt[MaxN], h[MaxN];
int lc[MaxS], rc[MaxS], sze[MaxS];
inline int ufs_find(int x)
{
return x == fa[x] ? x : fa[x] = ufs_find(fa[x]);
}
inline void insert(int &x, int l, int r, int pos)
{
if (!x) x = ++tot;
++sze[x];
if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid)
insert(lc[x], l, mid, pos);
else
insert(rc[x], mid + 1, r, pos);
}
inline int merge(int x, int y, int l, int r)
{
if (!x || !y) return x + y;
int mid = l + r >> 1;
lc[x] = merge(lc[x], lc[y], l, mid);
rc[x] = merge(rc[x], rc[y], mid + 1, r);
return sze[x] += sze[y], lc[y] = rc[y] = sze[y] = 0, x;
}
inline int query(int x, int l, int r, int k)
{
if (l == r) return l;
int mid = l + r >> 1, rsze = sze[rc[x]];
return k <= rsze ? query(rc[x], mid + 1, r, k) : query(lc[x], l, mid, k - rsze);
}
inline void link(int x, int y)
{
int u = ufs_find(x), v = ufs_find(y);
if (u == v) return;
fa[v] = u;
val[u] += val[v];
rt[u] = merge(rt[u], rt[v], 1, val_num);
}
int main()
{
read(n), read(m), read(Q);
for (int i = 1; i <= n; ++i)
read(h[i]), real[++val_num] = h[i];
std::sort(real + 1, real + val_num + 1);
val_num = std::unique(real + 1, real + val_num + 1) - real - 1;
for (int i = 1; i <= n; ++i)
h[i] = std::lower_bound(real + 1, real + val_num + 1, h[i]) - real;
for (int i = 1; i <= m; ++i)
e[i].scan();
for (int i = 1; i <= Q; ++i)
req[i].scan(i);
std::sort(e + 1, e + m + 1);
std::sort(req + 1, req + Q + 1);
for (int i = 1; i <= n; ++i)
{
fa[i] = i, val[i] = 1;
insert(rt[i], 1, val_num, h[i]);
}
int r = 0;
for (int i = 1; i <= Q; ++i)
{
while (r < m && e[r + 1].w <= req[i].x)
{
++r;
link(e[r].u, e[r].v);
}
int x = ufs_find(req[i].u);
int k = req[i].k;
ans[req[i].num] = k <= val[x] ? query(rt[x], 1, val_num, k) : 0;
}
real[0] = -1;
for (int i = 1; i <= Q; ++i)
putint(real[ans[i]]), putChar('\n');
putChar('\0');
return 0;
}
题目大意:给出一个 1 1 1 到 n n n 的排列,现在对这个序列进行 m m m 次局部排序,排序分为两种:
1.将区间 [ l , r ] [l,r] [l,r] 的数字升序排序
2.将区间 [ l , r ] [l,r] [l,r] 的数字降序排序
最后询问第 q q q 位置上的数字(询问只有最后一次)。 n , m ≤ 1 0 5 n,m\le 10^5 n,m≤105
//O(nlogn)
#include
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
const int MaxN = 1e5 + 5;
const int MaxS = MaxN * 20;
struct node
{
int l, r, opt, rt;
node(){}
node(int a, int b, int c, int d):
l(a), r(b), opt(c), rt(d) {}
inline bool operator < (const node &rhs) const
{
return r < rhs.r;
}
inline bool operator == (const node &rhs) const
{
return r == rhs.r;
}
};
typedef std::set<node>::iterator set_it;
int n, Q, tot;
int top, stk[MaxS];
int lc[MaxS], rc[MaxS], sze[MaxS];
std::set<node> S;
inline int get_new()
{
return top ? stk[top--] : ++tot;
}
inline void del(int x)
{
lc[x] = rc[x] = sze[x] = 0;
stk[++top] = x;
}
inline void insert(int &x, int l, int r, int pos)
{
if (!x) x = ++tot;
++sze[x];
if (l == r) return;
int mid = l + r >> 1;
pos <= mid ? insert(lc[x], l, mid, pos) : insert(rc[x], mid + 1, r, pos);
}
inline int merge(int x, int y, int l, int r)
{
if (!x || !y) return x + y;
if (l == r) return sze[x] += sze[y], del(y), x;
int mid = l + r >> 1;
lc[x] = merge(lc[x], lc[y], l, mid);
rc[x] = merge(rc[x], rc[y], mid + 1, r);
sze[x] = sze[lc[x]] + sze[rc[x]];
return del(y), x;
}
inline int query(int x, int l, int r, int k, int opt)
{
if (l == r) return l;
int mid = l + r >> 1;
if (opt)
{
int rs = sze[rc[x]];
return k <= rs ? query(rc[x], mid + 1, r, k, opt) : query(lc[x], l, mid, k - rs, opt);
}
else
{
int ls = sze[lc[x]];
return k <= ls ? query(lc[x], l, mid, k, opt) : query(rc[x], mid + 1, r, k - ls, opt);
}
}
inline void split(int x, int l, int r, int k, int opt, int &a, int &b)
{
if (!x) return (void)(a = b = 0);
if (!k) return (void)(a = 0, b = x);
if (l == r) return (void)(sze[b = k == sze[x] ? 0 : get_new()] = sze[x] - k, sze[a = x] = k);
int mid = l + r >> 1;
if (opt)
{
int rs = sze[rc[x]];
if (k <= rs)
a = get_new(), b = x, split(rc[x], mid + 1, r, k, opt, rc[a], rc[b]);
else
a = x, b = get_new(), split(lc[x], l, mid, k - rs, opt, lc[a], lc[b]);
}
else
{
int ls = sze[lc[x]];
if (k <= ls)
a = get_new(), b = x, split(lc[x], l, mid, k, opt, lc[a], lc[b]);
else
a = x, b = get_new(), split(rc[x], mid + 1, r, k - ls, opt, rc[a], rc[b]);
}
sze[a] = sze[lc[a]] + sze[rc[a]];
sze[b] = sze[lc[b]] + sze[rc[b]];
}
int main()
{
read(n), read(Q);
for (int i = 1; i <= n; ++i)
{
int now = 0, x;
read(x);
insert(now, 1, n, x);
S.insert(node(i, i, 0, now));
}
for (int i = 1; i <= Q; ++i)
{
int opt, l, r, u, v;
read(opt), read(l), read(r);
set_it it_l = S.lower_bound(node(l, l, 0, 0));
set_it it_r = S.lower_bound(node(r, r, 0, 0));
if (it_l == it_r)
{
int tl = it_l->l, tr = it_l->r, to = it_l->opt, tu = it_l->rt;
int u, v, w;
S.erase(it_l);
split(tu, 1, n, r - tl + 1, to, u, w);
split(u, 1, n, r - l + 1, to ^ 1, v, u);
if (tl < l) S.insert(node(tl, l - 1, to, u));
S.insert(node(l, r, opt, v));
if (r < tr) S.insert(node(r + 1, tr, to, w));
continue;
}
if (l != it_l->l)
{
split(it_l->rt, 1, n, l - it_l->l, it_l->opt, u, v);
int tl = it_l->l, tr = it_l->r, to = it_l->opt;
S.erase(it_l);
S.insert(node(tl, l - 1, to, u));
it_l = S.insert(node(l, tr, opt, v)).first;
}
if (r != it_r->r)
{
split(it_r->rt, 1, n, r - it_r->l + 1, it_r->opt, u, v);
int tl = it_r->l, tr = it_r->r, to = it_r->opt;
S.erase(it_r);
S.insert(node(r + 1, tr, to, v));
it_r = S.insert(node(tl, r, opt, u)).first;
}
for (set_it lst = it_l, it = ++it_l; it != S.end() && it->r <= r; lst = it, ++it)
{
int u = merge(lst->rt, it->rt, 1, n);
int tl = lst->l, tr = it->r;
S.erase(lst), S.erase(it);
it = S.insert(node(tl, tr, opt, u)).first;
}
}
int q_pos;
read(q_pos);
set_it it = S.lower_bound(node(q_pos, q_pos, 0, 0));
std::cout << query(it->rt, 1, n, q_pos - it->l + 1, it->opt) << std::endl;
return 0;
}
题目大意:给定一个点数、边数在 1 0 5 10^5 105 级别的无向图,求 S S S 到 T T T 的最短路,要求对 1 0 9 + 7 10^9+7 109+7 取模,并且输出最短路路径方案。每条边的边权形如 2 x ( 0 ≤ x ≤ 1 0 5 ) 2^x(0\le x\le 10^5) 2x(0≤x≤105)。
#include
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
template <class T>
inline void relax(T &x, const T &y)
{
if (x < y) x = y;
}
const int MaxNV = 1e5 + 555;
const int MaxNE = 2e5 + 5;
const int MaxS = MaxNV * 100;
const int base = 2;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
#define change(x, y) lc[x] = lc[y], rc[x] = rc[y], len[x] = len[y], sze[x] = sze[y], suf[x] = suf[y], val1[x] = val1[y], val2[x] = val2[y]
struct halfEdge
{
int v, w;
halfEdge *next;
}adj_pool[MaxNE], *adj[MaxNV], *adj_tail = adj_pool;
int n, m, src, des, lim, ans;
int p1[MaxNV], p2[MaxNV], rt[MaxNV], pre[MaxNV];
int tot, len[MaxS], val1[MaxS], val2[MaxS];
int lc[MaxS], rc[MaxS], sze[MaxS], suf[MaxS];
bool vis[MaxNV];
inline void addEdge(int u, int v, int w)
{
adj_tail->v = v;
adj_tail->w = w;
adj_tail->next = adj[u];
adj[u] = adj_tail++;
}
inline void print(int x, int l, int r)
{
// printf("prt %d:l = %d, r = %d, sze = %d, suf = %d\n:", x, l, r, sze[x], suf[x]);
if (!x || !sze[x]) return;
if (l == r) return (void)(ans = (ans + p1[l]) % mod1);
int mid = l + r >> 1;
print(lc[x], l, mid), print(rc[x], mid + 1, r);
}
inline void upt(int x, int l, int r)
{
int lenr = r - (l + r >> 1);
sze[x] = sze[lc[x]] + sze[rc[x]];
suf[x] = sze[rc[x]] == lenr ? lenr + suf[lc[x]] : suf[rc[x]];
val1[x] = (1LL * val1[lc[x]] * p1[lenr] + val1[rc[x]]) % mod1;
val2[x] = (1LL * val2[lc[x]] * p2[lenr] + val2[rc[x]]) % mod2;
}
inline void insert(int lst, int &x, int l, int r, int pos)
{
x = ++tot;
change(x, lst);
if (l == r)
{
sze[x] = suf[x] = val1[x] = val2[x] = 1;
return;
}
int mid = l + r >> 1;
pos <= mid ? insert(lc[lst], lc[x], l, mid, pos) : insert(rc[lst], rc[x], mid + 1, r, pos);
upt(x, l, r);
}
inline void del(int lst, int &x, int l, int r, int u, int v)
{
if (u <= l && r <= v) return (void)(x = 0);
x = ++tot;
change(x, lst);
int mid = l + r >> 1;
if (u <= mid) del(lc[lst], lc[x], l, mid, u, v);
if (v > mid) del(rc[lst], rc[x], mid + 1, r, u, v);
upt(x, l, r);
}
inline int query_suf(int x, int l, int r, int pos)
{
// printf("query:%d %d %d %d %d\n", x, l, r, pos, suf[lc[x]]);
if (!x || !sze[x]) return std::max(l, pos);
int mid = l + r >> 1;
if (pos > mid || suf[lc[x]] >= mid - pos + 1)
return query_suf(rc[x], mid + 1, r, std::max(pos, mid + 1));
else
return query_suf(lc[x], l, mid, pos);
}
inline bool cmp(int x, int y, int l, int r)
{
if (l == r) return sze[x] > sze[y];
int mid = l + r >> 1;
if (val1[rc[x]] == val1[rc[y]] && val2[rc[x]] == val2[rc[y]])
return cmp(lc[x], lc[y], l, mid);
else
return cmp(rc[x], rc[y], mid + 1, r);
}
struct node
{
int pos, u;
node(){}
node(int a, int b):
pos(a), u(b) {}
inline bool operator < (const node &rhs) const
{
return cmp(u, rhs.u, 0, lim);
}
};
std::priority_queue<node> heap;
inline void dfs(int u, int dep)
{
if (u == src)
{
printf("%d\n%d ", dep, u);
return;
}
dfs(pre[u], dep + 1);
printf("%d ", u);
}
int main()
{
read(n), read(m);
for (int i = 1; i <= m; ++i)
{
int u, v, w;
read(u), read(v), read(w);
addEdge(u, v, w);
addEdge(v, u, w);
relax(lim, w);
}
lim += 200;
read(src), read(des);
p1[0] = p2[0] = 1;
for (int i = 1; i <= lim; ++i)
p1[i] = 2LL * p1[i - 1] % mod1, p2[i] = 2LL * p2[i - 1] % mod2;
rt[src] = tot = 1, len[1] = lim + 1;
heap.push(node(src, 1));
while (!heap.empty())
{
node now = heap.top();
heap.pop();
int u = now.pos;
if (now.u != rt[u]) continue;
// ans = 0;
// printf("u:::%d-----\n", u);
// print(rt[u], 0, lim);
// printf("ans:%d\n", ans);
vis[u] = true;
if (u == des)
{
print(rt[des], 0, lim);
printf("%d\n", ans);
dfs(des, 1);
return 0;
}
for (halfEdge *e = adj[u]; e; e = e->next)
if (!vis[e->v])
{
int nxt;
// printf("(%d %d : %d %d\n", u, e->v, e->w, query_suf(rt[u], 0, lim, e->w));
int pos = query_suf(rt[u], 0, lim, e->w);
insert(rt[u], nxt, 0, lim, query_suf(rt[u], 0, lim, e->w));
if (e->w < pos)
del(nxt, nxt, 0, lim, e->w, pos - 1);
if (!rt[e->v] || cmp(rt[e->v], nxt, 0, lim))
heap.push(node(e->v, rt[e->v] = nxt)), pre[e->v] = u;
}
}
puts("-1");
return 0;
}
题目大意:给你一棵 n n n 个点的有根树,点有权值, m m m 次询问,每次问你某个点 u u u 的子树中距离其不超过 k k k 的点的权值的最小值。(边权均为 1 1 1,点权有可能重复, k k k 值每次询问有可能不同,强制在线) n , m ≤ 1 0 5 , a i ≤ 1 0 9 n,m\le 10^5,a_i\le10^9 n,m≤105,ai≤109
#include
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
inline void putChar(char ch)
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer;
if (ch == '\0')
fwrite(buffer, 1, head - buffer, stdout);
*head++ = ch;
if (head == tail)
fwrite(buffer, 1, buffer_size, stdout), head = buffer;
}
template <class T>
inline void putint(T x)
{
static char buf[15];
static char *tail = buf;
if (!x) putChar('0');
else
{
for (; x; x /= 10) *++tail = x % 10 + '0';
for (; tail != buf; --tail) putChar(*tail);
}
}
template <class T>
inline void relax(T &x, const T &y)
{
if (x < y) x = y;
}
template <class T>
inline void tense(T &x, const T &y)
{
if (x > y) x = y;
}
const int MaxNV = 1e5 + 5;
const int MaxNE = MaxNV << 1;
const int MaxS = MaxNV * 40;
const int INF = 0x7fffffff;
struct halfEdge
{
int v;
halfEdge *next;
}adj_pool[MaxNE], *adj_tail = adj_pool, *adj[MaxNV];
int n, Q;
int rt, dfs_clock, max_dep;
int ldfn[MaxNV], rdfn[MaxNV];
int a[MaxNV], dep[MaxNV];
std::vector<int> S[MaxNV];
int tot, seg[MaxNV];
int lc[MaxS], rc[MaxS], val[MaxS];
inline void copy(int x, int y)
{
lc[x] = lc[y], rc[x] = rc[y], val[x] = val[y];
}
inline void addEdge(int u, int v)
{
adj_tail->v = v;
adj_tail->next = adj[u];
adj[u] = adj_tail++;
}
inline void dfs_init(int u, int pre)
{
ldfn[u] = ++dfs_clock;
relax(max_dep, dep[u] = dep[pre] + 1);
S[dep[u]].push_back(u);
for (halfEdge *e = adj[u]; e; e = e->next)
if (e->v != pre)
dfs_init(e->v, u);
rdfn[u] = dfs_clock;
}
inline void insert(int lst, int &x, int l, int r, int pos, int del)
{
copy(x = ++tot, lst);
tense(val[x], del);
if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid)
insert(lc[lst], lc[x], l, mid, pos, del);
else
insert(rc[lst], rc[x], mid + 1, r, pos, del);
}
inline int query_min(int x, int l, int r, int u, int v)
{
if (!x) return INF;
if (u <= l && r <= v) return val[x];
int mid = l + r >> 1, res = INF;
if (u <= mid)
tense(res, query_min(lc[x], l, mid, u, v));
if (v > mid)
tense(res, query_min(rc[x], mid + 1, r, u, v));
return res;
}
int main()
{
val[0] = INF;
read(n), read(rt);
for (int i = 1; i <= n; ++i)
read(a[i]);
for (int i = 1; i < n; ++i)
{
int u, v;
read(u), read(v);
addEdge(u, v), addEdge(v, u);
}
dfs_init(rt, 0);
for (int i = 1; i <= max_dep; ++i)
{
std::vector<int> &T = S[i];
int lst = seg[i - 1];
for (int j = 0, jm = T.size(); j < jm; ++j)
{
int u = T[j];
insert(lst, lst, 1, n, ldfn[u], a[u]);
}
seg[i] = lst;
}
read(Q);
int last_ans = 0;
while (Q--)
{
int u, k;
read(u), read(k);
u = (u + last_ans) % n + 1;
k = (k + last_ans) % n;
int d = std::min(max_dep, dep[u] + k);
putint(last_ans = query_min(seg[d], 1, n, ldfn[u], rdfn[u]));
putChar('\n');
}
putChar('\0');
return 0;
}
一个 n n n 个结点的有根树,每个点有一个颜色, m m m 次询问,每次询问某一结点 u u u 中,深度不超过某个值 d e p [ u ] + d dep[u]+d dep[u]+d 的所有结点的颜色总数。对于每次询问 u , d u,d u,d 不一定相同。强制在线。
n , m ≤ 100000 n,m\le 100000 n,m≤100000
多组询问, 所有询问的 n , m n,m n,m 之和不超过 500000 500000 500000。
#include
inline char nextChar()
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer + buffer_size;
if (head == tail)
{
fread(buffer, 1, buffer_size, stdin);
head = buffer;
}
return *head++;
}
template <class T>
inline void read(T &x)
{
static char ch;
while (!isdigit(ch = nextChar()));
x = ch - '0';
while (isdigit(ch = nextChar()))
x = x * 10 + ch - '0';
}
inline void putChar(char ch)
{
static const int buffer_size = 2333333;
static char buffer[buffer_size];
static const char *tail = buffer + buffer_size;
static char *head = buffer;
if (ch == '\0')
fwrite(buffer, 1, head - buffer, stdout);
*head++ = ch;
if (head == tail)
fwrite(buffer, 1, buffer_size, stdout), head = buffer;
}
template <class T>
inline void putint(T x)
{
static char buf[22];
static char *tail = buf;
if (!x) return (void)(putChar('0'));
if (x < 0) x = ~x + 1, putChar('-');
for (; x; x /= 10) *++tail = x % 10 + '0';
for (; tail != buf; --tail) putChar(*tail);
}
template <class T>
inline void relax(T &x, const T &y)
{
if (x < y) x = y;
}
typedef std::set<int>::iterator set_it;
#define copy(x, y) sum[x] = sum[y], lc[x] = lc[y], rc[x] = rc[y]
const int MaxNV = 1e5 + 5;
const int MaxNE = MaxNV;
const int MaxLog = 18;
const int MaxS = MaxNV * MaxLog * 5;
struct halfEdge
{
int v;
halfEdge *next;
}adj_pool[MaxNE], *adj_tail, *adj[MaxNV];
int n, m, last_ans, dfs_clock, max_dep = 0;
int col[MaxNV], ldfn[MaxNV], rdfn[MaxNV], idx[MaxNV], dep[MaxNV];
int anc[MaxNV][MaxLog + 1];
std::set<int> S[MaxNV];
std::vector<int> vec[MaxNV];
int tot, rt[MaxNV];
int lc[MaxS], rc[MaxS], sum[MaxS];
inline void addEdge(int u, int v)
{
adj_tail->v = v;
adj_tail->next = adj[u];
adj[u] = adj_tail++;
}
inline void init()
{
for (int i = 1; i <= tot; ++i)
lc[i] = rc[i] = sum[i] = 0;
last_ans = max_dep = tot = dfs_clock = 0;
adj_tail = adj_pool;
for (int i = 1; i <= n; ++i)
{
adj[i] = NULL, vec[i].clear(), S[i].clear();
rt[i] = 0;
for (int j = 0; j <= MaxLog; ++j)
anc[i][j] = 0;
}
}
inline int query_lca(int u, int v)
{
if (dep[u] < dep[v]) std::swap(u, v);
for (int d = dep[u] - dep[v], i = 0; d; d >>= 1, ++i)
if (d & 1)
u = anc[u][i];
if (u == v) return u;
for (int i = MaxLog; i >= 0; --i)
if (anc[u][i] != anc[v][i])
{
u = anc[u][i];
v = anc[v][i];
}
return anc[u][0];
}
inline void dfs_init(int u)
{
idx[ldfn[u] = ++dfs_clock] = u;
vec[dep[u] = dep[anc[u][0]] + 1].push_back(u);
relax(max_dep, dep[u]);
for (int i = 0; anc[u][i]; ++i)
anc[u][i + 1] = anc[anc[u][i]][i];
for (halfEdge *e = adj[u]; e; e = e->next)
dfs_init(e->v);
rdfn[u] = dfs_clock;
}
inline void insert(int lst, int &x, int l, int r, int pos, int opt)
{
x = ++tot, copy(x, lst);
sum[x] += opt;
if (l == r) return;
int mid = l + r >> 1;
if (pos <= mid)
insert(lc[lst], lc[x], l, mid, pos, opt);
else
insert(rc[lst], rc[x], mid + 1, r, pos, opt);
}
inline int query_sum(int x, int l, int r, int u, int v)
{
if (!x) return 0;
if (u <= l && r <= v) return sum[x];
int mid = l + r >> 1, res = 0;
if (u <= mid)
res += query_sum(lc[x], l, mid, u, v);
if (v > mid)
res += query_sum(rc[x], mid + 1, r, u, v);
return res;
}
int main()
{
int T;
read(T);
while (T--)
{
read(n), read(m), init();
for (int i = 1; i <= n; ++i)
read(col[i]);
for (int i = 2; i <= n; ++i)
{
read(anc[i][0]);
addEdge(anc[i][0], i);
}
dfs_init(1);
for (int i = 1; i <= max_dep; ++i)
{
std::vector<int> &T = vec[i];
int lst = rt[i - 1];
for (int j = 0, jm = T.size(); j < jm; ++j)
{
int v = T[j];
set_it it1 = S[col[v]].insert(ldfn[v]).first, it2 = it1; ++it2;
insert(lst, lst, 1, n, ldfn[v], 1);
bool has_pre = it1 != S[col[v]].begin();
bool has_suf = it2 != S[col[v]].end();
set_it tmp = it1;
if (has_pre)
insert(lst, lst, 1, n, ldfn[query_lca(idx[*--it1], v)], -1);
if (has_suf)
insert(lst, lst, 1, n, ldfn[query_lca(idx[*it2], v)], -1);
if (has_pre && has_suf)
insert(lst, lst, 1, n, ldfn[query_lca(idx[*it1], idx[*it2])], 1);
}
rt[i] = lst;
}
for (int i = 1; i <= m; ++i)
{
int u, d;
read(u), read(d);
u ^= last_ans, d ^= last_ans;
d = std::min(max_dep, d + dep[u]);
putint(last_ans = query_sum(rt[d], 1, n, ldfn[u], rdfn[u]));
putChar('\n');
}
}
putChar('\0');
return 0;
}