题意:给定一棵树,每一个节点都有一些属性以及他们的状态,然后给定q个询问,每个询问问节点A的某个属性的状态,如果没有就往上咨询,直到有为止,如果没有就输出“N/A”(题目强制在线操作)。
解法:可持久化线段树,先对属性离散化(我用的是map),线段树维护当前节点以及往上的每一个属性的状态就好了,直接裸地维护就好了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <map>
#include <iostream>
using namespace std;
const int maxn = 300100;
map<string, int> g;
string s1, s2;
struct Node {
int l, r, l_point, r_point;
string s;
Node() {
l = 0; r = 0;
l_point = 0; r_point = 0;
s = "";
}
}a[20*maxn];
char c[30];
int last[maxn], pre[maxn];
int tot, n, m, start, num, syg;
void add_point(int cor_x, int x, int tar, string _s) {
if (a[x].l == a[x].r) {
a[x].s = _s;
return;
}
int mid = (a[x].l+a[x].r)/2;
if (tar <= mid) {
a[x].l_point = ++tot;
a[tot].l = a[x].l;
a[tot].r = mid;
a[x].r_point = a[cor_x].r_point;
add_point(a[cor_x].l_point, tot, tar, _s);
} else {
a[x].l_point = a[cor_x].l_point;
a[x].r_point = ++tot;
a[tot].l = mid+1;
a[tot].r = a[x].r;
add_point(a[cor_x].r_point, tot, tar, _s);
}
}
string find(int x, int tar) {
if (x == 0) return "N/A";
if (a[x].l == a[x].r) return a[x].s;
int mid = (a[x].l+a[x].r)/2;
if (tar <= mid) {
return find(a[x].l_point, tar);
} else {
return find(a[x].r_point, tar);
}
}
int main() {
scanf("%d", &n);
num = 0;
tot = 0;
syg = 0;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &pre[i], &m);
syg = last[pre[i]];
if (m == 0) last[i] = last[pre[i]];
while (m--) {
scanf("%s", c);
int len = strlen(c);
int j;
s1 = "";
for (j = 0; j < len; j++) {
if (c[j] == '=') break;
s1 = s1+c[j];
}
if (!g[s1]) g[s1] = ++num;
s2 = "";
for (j = j+1; j < len; j++) s2 = s2+c[j];
last[i] = tot+1;
int temp = tot+1;
tot++;
a[tot].l = 1; a[tot].r = maxn;
a[tot].l_point = a[tot].r_point = 0;
a[tot].s = "";
add_point(syg, tot, g[s1], s2);
syg = temp;
}
}
scanf("%d", &m);
while (m--) {
scanf("%d %s", &start, c);
s1 = c;
if (!g[s1]) {
cout << "N/A" << endl; cout.flush(); continue;
}
cout << find(last[start], g[s1]) << endl; cout.flush();
}
}