小清新点分治代码求条!小样例拍不出,但是大洋里输出0的时候几乎都不对
马蜂良好
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <cassert>
using namespace std;
inline long long read() {
long long num = 0, fg = 1;
char c = getchar();
while(!isdigit(c)) {
if (c =='-') fg = -fg;
c = getchar();
}
while(isdigit(c)) {
num = num * 10 + c - '0';
c = getchar();
}
return num * fg;
}
int n, m, c;
static const int inf = 0x3f3f3f3f;
static const int MAXN = 200005;
static const int MAXC = 50005;
int Q = 0;
struct Query {
int s, t;
int id;
};
Query q[MAXN];
int P[MAXN];
int w[MAXN];
int tmp[MAXN];
void sortp();
int head[MAXN];
int vert[MAXN];
int Next[MAXN];
int tot = 0;
void Link(int, int);
namespace Acc {
int solve();
}
#define DEBUG_ARRAY(ARR, LIM) \
printf(#ARR "[]:\n"); \
for (int i = 1; i <= LIM; i++) \
printf("%d ", ARR[i]); \
printf("\n");
int main() {
// 读入
n = read(), m = read(), c = read();
for (int i = 1; i <= c; i++) P[i] = read();
for (int i = 1; i <= n; i++) w[i] = read();
sortp();
for (int i = 1; i <= n - 1; i++) {
int x = read(), y = read();
Link(x, y);
Link(y, x);
}
Q = read();
for (int i = 1; i <= Q; i++) {
int s = read(), t = read();
q[i].s = s, q[i].t = t;
q[i].id = i;
}
// solve
Acc::solve();
return 0;
}
namespace Acc {
struct Segmt {
static const int SIZE = MAXN << 2;
struct SegmtNode {
int mx;
SegmtNode(): mx(0) { }
};
SegmtNode t[SIZE];
void pushup(int p) {
t[p].mx = max(t[p << 1].mx, t[p << 1 | 1].mx);
}
void modify(int pos, int dat, int l, int r, int p) {
if (l == r) {
t[p].mx = dat;
return ;
}
int mid = (l + r) >> 1;
if (pos <= mid) modify(pos, dat, l, mid, p << 1);
else modify(pos, dat, mid + 1, r, p << 1 | 1);
pushup(p);
}
void insert(int pos, int dat, int l, int r, int p) {
if (l == r) {
t[p].mx = max(t[p].mx, dat);
return ;
}
int mid = (l + r) >> 1;
if (pos <= mid) insert(pos, dat, l, mid, p << 1);
else insert(pos, dat, mid + 1, r, p << 1 | 1);
pushup(p);
}
int getmax(int nl, int nr, int l, int r, int p) {
if (nl == l && nr == r) {
return t[p].mx;
}
int mid = (l + r) >> 1;
if (nr <= mid) return getmax(nl, nr, l, mid, p << 1);
if (mid < nl) return getmax(nl, nr, mid + 1, r, p << 1 | 1);
return max(
getmax(nl, mid, l, mid, p << 1),
getmax(mid + 1, nr, mid + 1, r, p << 1 | 1)
);
}
int getval(int pos, int l, int r, int p) {
if (l == r) return t[p].mx;
int mid = (l + r) >> 1;
if (pos <= mid) return getval(pos, l, mid, p << 1);
return getval(pos, mid + 1, r, p << 1 | 1);
}
};
struct Stack {
int data[MAXN];
int top;
void push(int x) {
this->data[++this->top] = x;
}
int pop() {
return this->data[this->top--];
}
int get() {
return this->data[this->top];
}
int size() {
return this->top;
}
bool empty() {
return this->top == 0;
}
void clear() {
this->top = 0;
}
Stack(): top(0) { }
int &operator[](int index) {
return this->data[index];
}
};
int Root = 0;
int Tsiz = 0;
int siz[MAXN];
int mt[MAXN];
void GetRoot(int, int);
vector < int > qa[MAXN];
vector < int > qb[MAXN];
int vis[MAXN];
void work(int, int);
int apr[MAXN];
int tim = 0;
void dfs(int, int);
// col1 左半边的宝石数
// col2 答案
int col1[MAXN];
int col2[MAXN];
int pre[MAXN];
int num[MAXN];
int solve() {
for (int i = 1; i <= Q; i++) {
int s = q[i].s, t = q[i].t;
qa[s].push_back(i);
qb[t].push_back(i);
}
Tsiz = n;
Root = 0;
mt[Root] = inf;
GetRoot(1, 0);
GetRoot(Root, 0);
work(Root, 0);
for (int i = 1; i <= Q; i++) {
if (q[i].s == q[i].t) {
if (w[q[i].s] == 1) col2[i] = 1;
else col2[i] = 0;
}
}
for (int i = 1; i <= Q; i++) {
printf("%d\n", col2[i]);
}
return 0;
}
Stack q1;
int rem[MAXN];
int rtot = 0;
// 求 col1
void dfs1(int x, int fa) {
num[x] = w[x];
int lst = pre[w[x]];
pre[w[x]] = x;
num[x] = max(num[x], num[pre[w[x] + 1]]);
for (int i = head[x]; i; i = Next[i]) {
int y = vert[i];
if (y == fa || vis[y]) continue;
dfs1(y, x);
}
for (vector<int>::iterator it = qa[x].begin(); it != qa[x].end(); it++) {
int qid = *it;
q1.push(qid);
apr[qid] = tim;
}
if (w[x] == 1) {
while(!q1.empty()) {
int u = q1.pop();
col1[u] = num[x];
rem[++rtot] = u;
}
}
pre[w[x]] = lst;
}
Segmt t;
// 求 col2
void dfs2(int x, int fa) {
num[x] = w[x];
int lstpos = pre[w[x]];
pre[w[x]] = x;
if (num[pre[w[x] - 1]]) num[x] = min(num[x], num[pre[w[x] - 1]]);
else num[x] = w[x];
int lstcol = t.getval(num[x], 1, n, 1);
t.insert(num[x], w[x], 1, n, 1);
for (vector<int>::iterator it = qb[x].begin(); it != qb[x].end(); it++) {
int qid = *it;
if (apr[qid] != tim) continue;
int soucol = col1[qid];
int mxval = t.getmax(1, soucol + 1, 1, n, 1);
assert(col2[qid] == 0);
col2[qid] = max(mxval, col1[qid]);
}
for (int i = head[x]; i; i = Next[i]) {
int y = vert[i];
if (y == fa || vis[y]) continue;
dfs2(y, x);
}
t.modify(num[x], lstcol, 1, n, 1);
pre[w[x]] = lstpos;
}
Stack nodex;
void work2(int, int);
// 点分治主体函数:
void work(int x, int fa) {
vis[x] = true;
nodex.clear();
for (int i = head[x]; i; i = Next[i]) {
int y = vert[i];
if (y == fa || vis[y]) continue;
nodex.push(y);
}
num[x] = w[x];
int lstpos = pre[w[x]];
assert(lstpos == 0);
num[x] = max(num[x], num[pre[w[x] + 1]]);
pre[w[x]] = x;
// 由于路径有向,需要 reserve 一次重新做 dfs,所以有 2 个 work2();
work2(x, fa);
int nodex_siz = nodex.size();
for (int i = 1; i <= nodex_siz / 2; i++) {
swap(nodex[i], nodex[nodex_siz - i + 1]);
}
work2(x, fa);
pre[w[x]] = lstpos;
// 终点在 Root 上的询问,答案是左半边处理的宝石总数
for (vector<int>::iterator it = qb[x].begin(); it != qb[x].end(); it++) {
int qid = *it;
if (apr[qid] != tim) continue;
col2[qid] = col1[qid];
}
for (int i = head[x]; i; i = Next[i]) {
int y = vert[i];
if (y == fa || vis[y]) continue;
Root = 0;
mt[Root] = inf;
Tsiz = siz[y];
GetRoot(y, 0);
GetRoot(Root, 0);
work(Root, 0);
}
}
void work2(int x, int fa) {
tim++;
if (w[Root] == 1) for (vector<int>::iterator it = qa[Root].begin();
it != qa[Root].end(); it++) {
int qid = *it;
apr[qid] = tim;
col1[qid] = 1;
rem[++rtot] = qid;
}
for (int i = 1; i <= nodex.size(); i++) {
int y = nodex[i];
if (y == fa || vis[y]) continue;
// 求 起点在之前子树上的询问,终点在当前子树的 col2[].
dfs2(y, x);
// 求 起点在当前子树的的询问的 col1
dfs1(y, x);
if (w[Root] == 1) {
while(!q1.empty()) {
int u = q1.pop();
col1[u] = num[Root];
rem[++rtot] = u;
}
}
q1.clear();
}
for (int i = 1; i <= rtot; i++) {
col1[rem[i]] = false;
}
rtot = 0;
}
void GetRoot(int x, int fa) {
siz[x] = 1;
mt[x] = 0;
for (int i = head[x]; i; i = Next[i]) {
int y = vert[i];
if (y == fa || vis[y]) continue;
GetRoot(y, x);
siz[x] += siz[y];
mt[x] = max(mt[x], siz[y]);
}
mt[x] = max(mt[x], Tsiz - siz[x]);
if (mt[Root] > mt[x]) Root = x;
return ;
}
}
// sortp():: 重新定义 w[] .
void sortp() {
for (int i = 1; i <= c; i++) tmp[P[i]] = i;
for (int i = 1; i <= n; i++) w[i] = tmp[w[i]];
}
void Link(int x, int y) {
vert[++tot] = y;
Next[tot] = head[x];
head[x] = tot;
}
/*
7 10 5
1 2 3 4 5
1 2 3 5 2 4 1
1 2
1 3
2 4
2 5
3 6
6 7
1
5 4
*/