[ifrog 1072 Capture] 优先队列/线段树
知识点: tree
stl
优先队列
线段树
1. 题目链接
2. 题意描述
有一棵树,根节点为
1
,有
时间为:
15s
。。。
3. 解题思路
优先队列存放每个节点的深度。删点的时候,用dfs标记。查询的时候,取出没有被标记过的队首元素。这样的复杂度平摊下来也可以接受。因为每个节点最多进入一次优先队列,最多出来一次优先队列。
还有一种做法是,建树,求出dfs序,然后线段树对区间修改(删节点),单点修改(增加节点)以及区间查询(询问)操作。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int MAXN = 100000 + 5;
const int INF = 0x3f3f3f3f;
const LL INFL = 0x3f3f3f3f3f3f3f3fLL;
int n;
int id, tot, dep[MAXN], head[MAXN];
bool ok[MAXN];
struct Edge {
int v, next;
} edge[MAXN];
struct cmp {
bool operator() (const int& a, const int& b) const {
if(dep[a] == dep[b]) return a > b;
return dep[a] < dep[b];
}
};
priority_queue<int, vector<int>, cmp> q;
void init() {
memset(dep, -1, sizeof(dep));
memset(head, -1, sizeof(head));
memset(ok, false, sizeof(ok));
while(!q.empty()) q.pop();
dep[1] = 1;
tot = 0, id = 1;
ok[1] = true;
q.push(1);
}
void add_edge(int u, int v) {
edge[tot] = Edge{v, head[u]};
head[u] = tot ++;
}
void del(int u) {
if(!ok[u]) return;
ok[u] = false;
for(int i = head[u]; ~i; i = edge[i].next) {
del(edge[i].v);
}
}
void add(int u) {
if(!ok[u]) return;
int v = ++ id;
dep[v] = dep[u] + 1;
ok[v] = true;
add_edge(u, v);
q.push(v);
}
int query() {
while(!q.empty()) {
int u = q.top();
if(!ok[u]) {
q.pop();
continue;
}
return u;
}
return 1;
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
int _;
scanf("%d", &_);
while(_ --) {
init();
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
int u; scanf("%d", &u);
if(u < 0) del(-u);
else add(u);
printf("%d\n", query());
}
}
return 0;
}