SPOJ QTREE Query on a tree(边权LCT模板)
2015-08-01 11:53
661 查看
边权LCT...
一般用LCT搞边权有两种搞法,一种是类似树剖那样把边对应到点上,也就是除了根之外其他的节点都对应一条边,所以这样就不能换根,也就是不能进行树的分离和合并(好像如果LCT不能换根的话和树剖差不多了。。。);另一种是将每条边都当成一个点,然后将它的两个端点跟它连边,这样边权就转化成了点权,但是节点数多了一倍,可以实现各种操作。
一般用LCT搞边权有两种搞法,一种是类似树剖那样把边对应到点上,也就是除了根之外其他的节点都对应一条边,所以这样就不能换根,也就是不能进行树的分离和合并(好像如果LCT不能换根的话和树剖差不多了。。。);另一种是将每条边都当成一个点,然后将它的两个端点跟它连边,这样边权就转化成了点权,但是节点数多了一倍,可以实现各种操作。
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<set> #include<algorithm> using namespace std; #define LL long long #define eps 1e-8 #define MP make_pair #define N 20020 #define M 80020 #pragma comment(linker, "/STACK:1024000000,1024000000") #define ls (i << 1) #define rs (ls | 1) #define md ((ll + rr) >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs #define mod 258280327 #define inf 0x3f3f3f3f #define ULL unsigned long long int readint() { char c; while((c = getchar()) && !(c >= '0' && c <= '9')); int ret = c - '0'; while((c = getchar()) && c >= '0' && c <= '9') ret = ret * 10 + c - '0'; return ret; } int n, m; int ch [2], key , pre , rev ; bool rt ; int fst , nxt[M], vv[M], e; int val ; int mx ; void init() { for(int i = 1; i <= n + n - 1; ++i) { rt[i] = 1; fst[i] = -1; ch[i][0] = ch[i][1] = 0; pre[i] = 0; val[i] = 0; rev[i] = 0; } e = 0; } void add(int u, int v) { vv[e] = v, nxt[e] = fst[u], fst[u] = e++; } void dfs(int u, int p) { pre[u] = p; mx[u] = val[u]; key[u] = val[u]; for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(v != p) dfs(v, u); } } void update_rev(int x) { if(!x) return; rev[x] ^= 1; swap(ch[x][0], ch[x][1]); } void push_down(int x) { if(rev[x]) { update_rev(ch[x][0]); update_rev(ch[x][1]); rev[x] = 0; } } void push_up(int x) { mx[x] = key[x]; mx[x] = max(mx[x], mx[ch[x][0]]); mx[x] = max(mx[x], mx[ch[x][1]]); } void rot(int x) { int y = pre[x], d = ch[y][1] == x; ch[y][d] = ch[x][!d]; pre[ch[x][!d]] = y; pre[x] = pre[y]; pre[y] = x; ch[x][!d] = y; if(rt[y]) rt[y] = false, rt[x] = true; else ch[pre[x]][ch[pre[x]][1]==y] = x; push_up(y); } void P(int x) { if(!rt[x]) P(pre[x]); push_down(x); } void splay(int x) { P(x); while(!rt[x]) { int f = pre[x], ff = pre[f]; if(rt[f]) rot(x); else if((ch[ff][1] == f) == (ch[f][1] == x)) rot(f), rot(x); else rot(x), rot(x); } push_up(x); } void Access(int x) { int y = 0; for(; x; y = x, x = pre[x]) { splay(x); rt[ch[x][1]] = true; ch[x][1] = y; rt[y] = false; push_up(x); } } void lca(int &u, int &v) { Access(v), v = 0; for(splay(u); pre[u]; v = u, u = pre[u], splay(u)) { rt[ch[u][1]] = true; ch[u][1] = v; rt[v] = false; push_up(u); } } void make_root(int x) { Access(x); splay(x); update_rev(x); } int query(int u, int v) { /* lca(u, v); int ret = key[u]; ret = max(ret, mx[v]); ret = max(ret, mx[ch[u][1]]); */ make_root(u); Access(v); splay(v); return mx[v]; } int main() { int cas; scanf("%d", &cas); while(cas--) { scanf("%d", &n); init(); for(int i = 1; i < n; ++i) { int u, v, c; scanf("%d%d%d", &u, &v, &c); add(i + n, u); add(u, i + n); add(i + n, v); add(v, i + n); val[i+n] = c; } dfs(1, 0); char s[10]; while(1) { scanf("%s", s); if(s[0] == 'D') break; int u, v; scanf("%d%d", &u, &v); if(s[0] == 'Q') { make_root(u); Access(v); splay(v); printf("%d\n", mx[v]); } else { splay(u + n); key[u+n] = v; push_up(u + n); } } } return 0; }
相关文章推荐
- NGUI之UI模块基类
- EasyUI学习网站
- druid配置
- 设置uitextview边框
- 错误提示:连接 built-in.o 提示 undefined reference to
- IOS 自定义 tableView cell(UITableViewCell height) 高度
- SolrCloud Wiki翻译(4)Distributed Requests
- UITextfield
- POJ 1679 The Unique MST
- UILabel
- 通过UIAlertView或者ActionSheet控件调用share方法
- UIView
- poj 1019 Number Sequence 【组合数学+数字x的位宽函数】
- UITableViewCell 输入框动态变高
- Ueditor上传图片到本地改造到上传图片到云存储
- 随机生成UUID的工具类
- iOS开发UI篇—transframe属性(形变)
- Serializable serialVersionUID
- UIViewController 视图控制器
- UIButton,UITextField