SPOJ 2939 QTREE5 - Query on a tree V

来源:互联网 发布:如何在淘宝做代理商 编辑:程序博客网 时间:2024/06/05 05:11

这道题与QTREE4类似

难度两者差不多 , 这个版本没有边权(但做过QTREE4的小伙伴都知道边权其实并不会增加难度) , 但是多了一些查找操作。

值得一说的:
对于线段树而言 , 我想大家比较习惯的方式是从上往下递归修改 , 所以这里(QTREE4也是)使用了一个 findPath() 的函数。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <queue>#include <set>#include <map>#include <algorithm>using namespace std;const int maxn = 1e5+1e2;const int INF = 0x3f3f3f3f;struct node{ int l , r; node(int l = 0 , int r = 0):l(l),r(r){} };int n , dfsCnt , cnt , cs;int fa[maxn] , id[maxn] , reid[maxn] , bl[maxn] , Size[maxn] , s[maxn] , c[maxn];vector<int> g[maxn];void dfs(int u){    Size[u] = 1;    for(int i=0;i<g[u].size();i++)    {        int t = g[u][i];        if(t == fa[u]) continue;        fa[t] = u;        dfs(t);        Size[u] += Size[t];    }}void dfs(int u , int num){    reid[id[u] = ++dfsCnt] = u;    bl[u] = num;    s[num]++;    int mx = 0 , w;    for(int i=0;i<g[u].size();i++)    {        int t = g[u][i];        if(t == fa[u]) continue;        if(mx < Size[t]) mx = Size[t] , w = t;    }    if(mx) dfs(w, num);    for(int i=0;i<g[u].size();i++)    {        int t = g[u][i];        if(t == fa[u] || t == w) continue;        dfs(t, t);          }}node seg[maxn*4];int ls[maxn*4] , rs[maxn*4] , root[maxn];multiset<int> ch[maxn];node merge(node& a , node& b , int l1 , int l2 , int l3) {    node res;    res.l = min(a.l , l1+l2+b.l);    res.r = min(b.r , l2+l3+a.r);    return res;}void maintain(int o , int x){    int d1 = INF , d2 = INF; if(c[x]) d1 = d2 = 0;    if(ch[x].size()) d1 = min(d1 , *ch[x].begin());    if(ch[x].size()>1) d2 = min(d2 , *(++ch[x].begin()));    seg[o].l = seg[o].r = d1;}void build(int o , int l , int r){    if(l==r)    {        int x = reid[l];        for(int i=0;i<g[x].size();i++)        {            int t = g[x][i];            if(t == fa[x] || bl[t] == bl[x]) continue;            build(root[t] = ++cnt, id[t], id[t]+s[t]-1);            ch[x].insert(seg[root[t]].l+1);        }        maintain(o, x);    }    else     {        int mid = (l+r)/2;        build(ls[o] = ++cnt, l, mid);        build(rs[o] = ++cnt, mid+1, r);        seg[o] = merge(seg[ls[o]], seg[rs[o]], mid-l, 1, r-mid-1);    }}deque<int> pat;void findPath(int x){    pat.clear();    int l = 0;    while(x)    {        int f = bl[x];        pat.push_front(l);        pat.push_front(x);        pat.push_front(f);        l += id[x] - id[f] + 1;        x = fa[f];    }}void modify(int o , int l , int r , int i){    if(l == r)    {        int x = reid[l];        if(i+3 < pat.size())        {            int ne = pat[i+2];            ch[x].erase(ch[x].find(seg[root[ne]].l+1));            modify(root[ne], id[ne], id[ne]+s[ne]-1, i+3);            ch[x].insert(seg[root[ne]].l+1);        }        maintain(o, x);    }    else     {        int mid = (l+r)/2;        if(id[pat[i]] <= mid) modify(ls[o], l, mid, i);        else modify(rs[o], mid+1, r, i);        seg[o] = merge(seg[ls[o]], seg[rs[o]], mid-l, 1, r-mid-1);    }}int query(int o , int l , int r , int i){    if(l==r)    {        int res = INF;        if(i+3<pat.size())        {            int ne = pat[i+2];            res = query(root[ne], id[ne], id[ne]+s[ne]-1, i+3);        }        res = min(res , seg[o].l+pat[i+1]);        return res;    }    else     {        int mid = (l+r)/2 , res;        if(id[pat[i]] <= mid) res = min(query(ls[o], l, mid, i) , mid+1-id[pat[i]]+seg[rs[o]].l+pat[i+1]);        else res = min(query(rs[o], mid+1, r, i) , seg[ls[o]].r+id[pat[i]]-mid+pat[i+1]);        return res;    }}int main(int argc, char *argv[]) {    cin>>n;    for(int i=1;i<n;i++)    {        int a ,b;        scanf("%d%d" , &a , &b);        g[a].push_back(b);        g[b].push_back(a);    }    dfs(1);    dfs(1, 1);    build(root[1] = ++cnt, 1, s[1]);    int x , y , Q;    cin>>Q;    while(Q--)    {        scanf("%d%d" , &x , &y);        if(x)         {            if(!cs) { puts("-1"); continue; }            findPath(y);            printf("%d\n" , query(1, 1, s[1], 1));        }        else         {            cs += 1 - c[y]*2;            c[y] = 1-c[y];            findPath(y);            modify(1, 1, s[1], 1);        }    }    return 0;}
0 0
原创粉丝点击