LCT 动态树 hdu 5002
2016-03-11 16:44
337 查看
LCT的模板题,当做是学了一个模板 #include<cstdio> #include<cstring> #include<vector> #include<iostream> #include<algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N = 111111; int m,n; class LCT { private: struct node { int size,same,rev,val,inc; pair<int,int> value[2]; node *ch[2],*f; bool isroot; inline void setchild(node *tmp,int dir) { ch[dir] = tmp; tmp->f = this; } inline int isrc() { return f->ch[1] == this; } int calc(int v) { int res = 0; if(val == v) res++; for(int i = 0;i < 2;i++) { for(int j = 0;j < 2;j++) { if(this->ch[i]->value[j].first == v) { res+= this ->ch[i] ->value[j].second; } } } return res; } inline void update() { if(size == 0) { return ; } int maxvalue = max(max(ch[0]->value[0].first,ch[1]->value[0].first),val); value[0] = make_pair(maxvalue,this->calc(maxvalue)); int sec = -INF; if(val != maxvalue) { sec = max(sec,val); } for(int i = 0;i < 2;i++) { for(int j = 0;j < 2;j++) { if(this -> ch[i] ->value[j].first!=maxvalue) { sec = max(sec,this->ch[i] -> value[j].first); } } } value[1] = make_pair(sec,this->calc(sec)); size = 1 + ch[0]->size + ch[1] -> size; } inline void make(int v) { if(size == 0) { return ; } value[0] = make_pair(v,size); value[1] = make_pair(-INF,0); same = v; inc = 0; val = v; } inline void add(int v) { if(size == 0) return ; inc+=v; val+=v; if(value[0].first != -INF) { value[0].first+= v; } if(value[1].first != -INF) { value[1].first+=v; } } inline void reverse() { if(size == 0) return ; rev^=1;swap(ch[0],ch[1]); } inline void push() { if(size == 0) return ; if(rev) { ch[0]->reverse(); ch[1]->reverse(); rev = 0; } if(same!=-INF) { ch[0]->make(same); ch[1] -> make(same); same = -INF; } if(inc) { ch[0]->add(inc); ch[1]->add(inc); inc = 0; } } }; typedef node *Node; node mem ; int used; Node Null,t ; Node newnode(int v) { Node tmp = &mem[used++]; tmp->size = 1;tmp->same = -INF;tmp->rev =0;tmp->val = v;tmp->inc = 0; tmp->value[0] = make_pair(v,1); tmp->value[1] = make_pair(-INF,0); tmp->ch[0] = tmp->ch[1] = tmp->f = Null; tmp->isroot = true; return tmp; } void rotate(Node root) { Node father = root->f; father->push();root->push(); int dir = root->isrc(); father->setchild(root->ch[!dir],dir); if(father->isroot) { father -> isroot = false; root->isroot = true; root -> f = father ->f; } else father->f->setchild(root,father->isrc()); root -> setchild(father,!dir); father->update(); } void splay(Node root) { for(root -> push();!root->isroot;) { if(root->f->isroot) rotate(root); else { (root -> isrc() == root -> f -> isrc())?(r 4000 otate(root -> f),rotate(root)):(rotate(root),rotate(root)); } } root->update(); } void access(Node root,int oper = 0,int val = 0) { for(Node tmp(Null);root!=Null;) { splay(root); if(root->f == Null&&oper) { if(oper == 1) { tmp->make(val); root->push(); root ->ch[1]->make(val); root->val = val; root->update(); } if(oper == 2) { tmp->add(val); root -> push(); root->ch[1]->add(val); root->val+=val; root->update(); } } root->ch[1]->isroot = true; root->ch[1] = tmp; root->ch[1] -> isroot = false; root->update(); tmp = root; root = root->f; } } public: void init(int a,int val[]) { used = 0; Null = newnode(-INF); Null->f = Null->ch[0] = Null->ch[1] = Null; Null -> size = 0; for(int i = 1;i <= a;i++) { t[i] = newnode(val[i]); } } void link(int son,int father) { access(t[son]); splay(t[son]); t[son] ->f = t[father]; t[son]->reverse(); } void cut(int u,int v) { access(t[v]); splay(t[u]); if(t[u]->f == t[v]) { t[u]->f = Null; } else { access(t[u]); splay(t[v]); if(t[v]->f == t[u]) { t[v]->f = Null; } } } void makesame(int u,int v,int val) { access(t[u]); access(t[v],1,val); } void add(int u,int v,int val) { access(t[u]); access(t[v],2,val); } pair<int,int> getvalue(int u,int v) { access(t[u]); Node root = t[v]; pair<int,int>res; for(Node tmp(Null);root!=Null;) { splay(root); if(root->f==Null) { root->push(); Node a = tmp,b = root->ch[1]; vector<int> vv; vv.push_back(root->val); for(int i = 0;i < 2;i++) { vv.push_back(a->value[i].first); vv.push_back(b->value[i].first); } sort(vv.begin(),vv.end()); vv.erase(unique(vv.begin(),vv.end()),vv.end()); reverse(vv.begin(),vv.end()); while(vv.size()&&vv.back() == -INF) { vv.pop_back(); } if(vv.size() == 1) { res = make_pair(-INF,0); } else { res = make_pair(vv[1],0); for(int i = 0;i < 2;i++) { if(a->value[i].first == vv[1]) { res.second += a->value[i].second; } if(b->value[i].first==vv[1]) { res.second += b->value[i].second; } } res.second+=(root->val == vv[1]); } } root->ch[1]->isroot = true; root->ch[1] = tmp; root -> ch[1] -> isroot = false; root->update(); tmp = root; root = root -> f; } return res; } }tree; int main() { int test; scanf("%d", &test); while(test--) { static int testCount = 0; printf("Case #%d:\n", ++testCount); scanf("%d %d", &n, &m); static int val ; for(int i = 1; i <= n; i++) { scanf("%d", &val[i]); } tree.init(n, val); for(int i = 1; i < n; i++) { int a, b; scanf("%d %d", &a, &b); tree.link(a, b); } for(int i = 1; i <= m; i++) { int type, a, b, x, y; scanf("%d", &type); if (type == 1) { scanf("%d %d %d %d", &x, &y, &a, &b); tree.cut(x, y); tree.link(a, b); } else if (type == 2) { scanf("%d %d %d", &a, &b, &x); tree.makesame(a, b, x); } else if (type == 3) { scanf("%d %d %d", &a, &b, &x); tree.add(a, b, x); } else { int a, b; scanf("%d %d", &a, &b); pair<int, int> temp = tree.getvalue(a, b); if (temp.first == -INF) { printf("ALL SAME\n"); } else { printf("%d %d\n", temp.first, temp.second); } } } } return 0; }
相关文章推荐
- python常用的备份脚本
- 事件
- MATLAB数据降维工具箱drtoolbox介绍
- 博文的学习路线
- 带标记的ImageView,图片可以设置成圆角
- shell数组用法
- 使用java反射机制对类字段进行选择性校验示例
- Linux命令行下vim指令笔记
- android启动出错
- SQL查询语句去除重复行
- 个人项目——二柱子程序升级版
- jquery选择器 之 获取父级元素、同级元素、子元素
- PHP无限分类-左右值实现
- Android so文件是32位时,如何在64位手机上运行。
- RunLoop 理解(转)
- 哪家服务器租用和托管便宜
- 精通 Grails: 构建您的第一个 Grails 应用程序
- Swift学习 数组
- nefu481(二分图,最小路径覆盖)(毁三观。。)
- NodeJS写日志_Log4js使用详解+常见艰难的解决