博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SPOJ 2798 Query on a tree again!
阅读量:6640 次
发布时间:2019-06-25

本文共 3237 字,大约阅读时间需要 10 分钟。

SPOJ_2798

    如果用link-cut-tree写的话,只要维护col(节点的颜色)和sum(子树中black节点的数量)两个标记即可。染色的时候将对应节点splay到根然后修改,查询的时候先进行access(v)的操作,之后找到这棵splay的根再递归查找即可,如果根结点的sum值为0,则输出-1。

#include
#include
#define MAXD 100010#define MAXM 200010int N, Q, q[MAXD], first[MAXD], e, next[MAXM], v[MAXM];struct Splay{ int pre, ls, rs, col, sum; bool root; void update(); void zig(int ); void zag(int ); void splay(int ); void renew() { root = true; pre = ls = rs = 0; col = 0, sum = 0; }}sp[MAXD];void Splay::update(){ sum = sp[ls].sum + sp[rs].sum + col;}void Splay::zig(int x){ int y = rs, fa = pre; rs = sp[y].ls, sp[rs].pre = x; sp[y].ls = x, pre = y; sp[y].pre = fa; if(root) root = false, sp[y].root = true; else sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update();}void Splay::zag(int x){ int y = ls, fa = pre; ls = sp[y].rs, sp[ls].pre = x; sp[y].rs = x, pre = y; sp[y].pre = fa; if(root) root = false, sp[y].root = true; else sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update();}void Splay::splay(int x){ int y, z; for(; !root;) { y = pre; if(sp[y].root) sp[y].rs == x ? sp[y].zig(y) : sp[y].zag(y); else { z = sp[y].pre; if(sp[z].rs == y) { if(sp[y].rs == x) sp[z].zig(z), sp[y].zig(y); else sp[y].zag(y), sp[z].zig(z); } else { if(sp[y].ls == x) sp[z].zag(z), sp[y].zag(y); else sp[y].zig(y), sp[z].zag(z); } } } update();}void add(int x, int y){ v[e] = y; next[e] = first[x], first[x] = e ++;}void prepare(){ int i, j, x, rear = 0; sp[0].sum = 0; q[rear ++] = 1; sp[1].renew(); for(i = 0; i < rear; i ++) { x = q[i]; for(j = first[x]; j != -1; j = next[j]) if(v[j] != sp[x].pre) { sp[v[j]].renew(), sp[v[j]].pre = x; q[rear ++] = v[j]; } }}void init(){ int i, x, y; memset(first, -1, sizeof(first)); e = 0; for(i = 1; i < N; i ++) { scanf("%d%d", &x, &y); add(x, y), add(y, x); } prepare();}void change(int x){ sp[x].splay(x); sp[x].col ^= 1; sp[x].update();}void access(int x){ int fx; for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre) { sp[fx].splay(fx); sp[sp[fx].rs].root = true; sp[fx].rs = x, sp[x].root = false; sp[fx].update(); }}int Search(int cur){ if(sp[sp[cur].ls].sum != 0) return Search(sp[cur].ls); else if(sp[cur].col) return cur; else return Search(sp[cur].rs);}void ask(int x){ int y; access(x); for(y = x; !sp[y].root; y = sp[y].pre); if(sp[y].sum == 0) printf("-1\n"); else printf("%d\n", Search(y));}void solve(){ int i, op, x; for(i = 0; i < Q; i ++) { scanf("%d%d", &op, &x); if(op == 0) change(x); else ask(x); }}int main(){ while(scanf("%d%d", &N, &Q) == 2) { init(); solve(); } return 0;}

转载地址:http://djovo.baihongyu.com/

你可能感兴趣的文章
國王遊戲(2012年NOIP全国联赛提高组)
查看>>
谈谈 ES6 的 Promise 对象
查看>>
PHP $_SERVER['PHP_SELF']、$_SERVER['SCRIPT_NAME'] 与 $_SERVER['REQUEST_URI'] 之间的区别
查看>>
创业者要有杀手气质和传教士能力
查看>>
Eclipse报错Resource '/.org.eclipse.jdt.core.external.folders/.link5' already exists.
查看>>
jmeter实例,如果有说明错误,请各位大神批评
查看>>
模拟时间--延时处理
查看>>
Linq 中按照多个值进行分组(GroupBy,Count)
查看>>
平常的一天,让我忘记了很多
查看>>
Sqoop2搭建及使用
查看>>
solr入门之pinyin4j源代码改写动态加入扩展词及整合进war项目中
查看>>
写网页常用
查看>>
CAFFE安装(4):ATLAS/ Intel MKL安装
查看>>
升级到win10之后word和excel提示“向程序发送命令时出现问题”解决方法
查看>>
Linux CentOS7.5静默安装Oracle11gR2
查看>>
Ubuntu下压缩文件
查看>>
TEAMWORK2
查看>>
定时器的编写
查看>>
无服务架构综述
查看>>
vue vuex初学基础 常见错误解决方式
查看>>