hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
2013-11-15 17:17
411 查看
Treap树入门练习题目,此题主要来练习Treap的操作
此题也是刘汝佳 大白书,Treap的例题
用指针实现的Treap的操作
注意:
1.不要访问NULL
2.cmp函数的使用,相等时返回-1
其它,待补充。。。
另:
为避免错误和是操作的简洁,可使用一个真实的空指针null代替空指针NULL,。。。
关于内存预申请的优化写法,待补充
使用了null的代码:
此题也是刘汝佳 大白书,Treap的例题
用指针实现的Treap的操作
注意:
1.不要访问NULL
2.cmp函数的使用,相等时返回-1
其它,待补充。。。
另:
为避免错误和是操作的简洁,可使用一个真实的空指针null代替空指针NULL,。。。
关于内存预申请的优化写法,待补充
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FD(i, b, a) for(int i = (b); i >= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(a, v) memset(a, v, sizeof(a)) #define PB push_back #define MP make_pair typedef long long LL; const int INF = 0x3f3f3f3f; struct Node { Node *ch[2]; int r; ///随机优先级 int v; ///值 int s; ///节点总数 Node(int v) : v(v) { ch[0] = ch[1] = NULL; r = rand(); s = 1; }/// bool operator < (const Node &rhs) const { return r < rhs.r; } int cmp(int x) const { if (x == v) return -1; return x < v ? 0 : 1; } void pushup() { s = 1; if (ch[0] != NULL) s += ch[0]->s; if (ch[1] != NULL) s += ch[1]->s; } }; ///不用确保o有孩子节点吗? void rotate(Node* &o, int d) { Node* k = o->ch[d ^ 1]; o->ch[d ^ 1] = k->ch[d]; k->ch[d] = o; o->pushup(); k->pushup(); ///先o后k o = k; } void insert(Node* &o, int x) { if (o == NULL) o = new Node(x); else { int d = (x < o->v ? 0 : 1);///不要用cmp函数,可能有相同节点 insert(o->ch[d], x); if (o->ch[d] > o) rotate(o, d ^ 1); } o->pushup(); } void remove(Node* &o, int x) { int d = o->cmp(x); if (d == -1) { Node* u = o; if (o->ch[0] != NULL && o->ch[1] != NULL) { int d2 = (o->ch[0] > o->ch[1] ? 1 : 0); rotate(o, d2); remove(o->ch[d2], x); } else { if (o->ch[0] == NULL) o = o->ch[1]; else o = o->ch[0]; delete u; ///!!! } } else remove(o->ch[d], x); if (o != NULL) o->pushup(); } const int maxc = 500000 + 10; const int maxn = 20000 + 10; const int maxm = 60000 + 10; struct Command { char type; int x, p; Command(){} Command(char type, int x, int p) : type(type), x(x), p(p){} }Q[maxc]; int n, m; int weight[maxn]; int from[maxm], to[maxm], removed[maxm]; ///并查集相关 int fa[maxn]; void init_fa(int n) { REP(i, n + 1) fa[i] = i; } int findset(int x) { return fa[x] == x ? x : fa[x] = findset(fa[x]); } /// 名次树相关 Node* root[maxn]; ///查第k大 int kth(Node* o, int k) { if (o == NULL || k <= 0 || k > o->s) return 0;///没成功查到,!!!!! int s = (o->ch[1] == NULL ? 0 : o->ch[1]->s); if (k == s + 1) return o->v; if (k <= s) return kth(o->ch[1], k); else return kth(o->ch[0], k - s - 1); } void mergeto(Node* &src, Node* &dest) { if (src->ch[0] != NULL) mergeto(src->ch[0], dest); if (src->ch[1] != NULL) mergeto(src->ch[1], dest); insert(dest, src->v);/// delete(src); src = NULL; } void removetree(Node* &o) { if (o->ch[0] != NULL) removetree(o->ch[0]); if (o->ch[1] != NULL) removetree(o->ch[1]); delete(o); o = NULL; } ///主程序相关 void add_edge(int x) { int u = findset(from[x]), v = findset(to[x]); if (u != v) { if (root[u]->s < root[v]->s) { fa[u] = v; mergeto(root[u], root[v]); } else { fa[v] = u; mergeto(root[v], root[u]); } } } int Q_cnt; LL Q_tot; void query(int x, int k) { Q_cnt++; Q_tot += kth(root[findset(x)], k); } void change_weight(int x, int v) { int u = findset(x); remove(root[u], weight[x]); insert(root[u], v); weight[x] = v; } int nc; void solve(int c) { Q_tot = Q_cnt = 0; for (int i = c - 1; i >= 0; i--) { if (Q[i].type == 'D') add_edge(Q[i].x); else if (Q[i].type == 'Q') query(Q[i].x, Q[i].p); else change_weight(Q[i].x, Q[i].p); } printf("Case %d: %.6lf\n", nc++, Q_tot / (1.0 * Q_cnt)); } int main () { nc = 1; while (scanf("%d%d", &n, &m) == 2 && n) { for (int i = 1; i <= n; i++) scanf("%d", &weight[i]); for (int i = 1; i <= m; i++) scanf("%d%d", &from[i], &to[i]); CLR(removed, 0); int c = 0; while (1) { char type; int x, p = 0, v = 0; scanf(" %c", &type); if (type == 'E') break; scanf("%d", &x); if (type == 'D') removed[x] = 1; if (type == 'Q') scanf("%d", &p); if (type == 'C') { scanf("%d", &v); p = weight[x];/// weight[x] = v; } Q[c++] = Command(type, x, p); } ///最终图 init_fa(n); for (int i = 1; i <= n; i++) { if (root[i] != NULL) removetree(root[i]); root[i] = new Node(weight[i]); } for (int i = 1; i <= m; i++) { if (!removed[i]) add_edge(i); } ///反向操作 solve(c); } return 0; }
使用了null的代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FD(i, b, a) for(int i = (b); i >= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(a, v) memset(a, v, sizeof(a)) #define PB push_back #define MP make_pair typedef long long LL; const int INF = 0x3f3f3f3f; const int MAXN = 100010; struct Node{ Node *ch[2]; int r, v, s; Node(){} Node(int v, Node *null):v(v){ ch[0] = ch[1] = null; s = 1; r = rand(); } int cmp(int x) { if (v == x) return -1; return x < v ? 0 : 1; } void maintain() { s = ch[0]->s + ch[1]->s + 1; } bool operator<(const Node& rhs) const { return r < rhs.r; } }*null; void rotate(Node* &rt, int d) { Node* k = rt->ch[d ^ 1]; rt->ch[d ^ 1] = k->ch[d]; k->ch[d] = rt; rt->maintain(); k->maintain(); rt = k; } void insert(Node* &rt, int x) { if (rt == null) { rt = new Node(x, null); } else { int d = x < rt->v ? 0 : 1; insert(rt->ch[d], x); if (rt < rt->ch[d]) rotate(rt, d ^ 1); } rt->maintain(); } void remove(Node* &rt, int x) { int d = rt->cmp(x); if (d == -1) { Node* u = rt; if (rt->ch[0] != null && rt->ch[1] != null) { int d2 = rt->ch[0] > rt->ch[1] ? 1 : 0; rotate(rt, d2); remove(rt->ch[d2], x); } else { if (rt->ch[0] == null) rt = rt->ch[1]; else rt = rt->ch[0]; delete(u); } } else remove(rt->ch[d], x); if (rt != null) rt->maintain(); } const int maxc = 500000 + 10; const int maxn = 20000 + 10; const int maxm = 60000 + 10; ///名次树相关 Node *root[maxn]; void init_root() { null = new Node(); null->ch[0] = null->ch[1] = null; null->r = null->v = null->s = 0; for (int i= 0; i < maxn; i++) root[i] = null; } int kth(Node *rt, int k) { if (rt == null || k <= 0 || k > rt->s) return 0; // int ss = rt->ch[1] == null ? 0 : rt->ch[1]->s;///!!! int ss = rt->ch[1]->s; if (k == ss + 1) return rt->v; else if (k < ss + 1) return kth(rt->ch[1], k); else return kth(rt->ch[0], k - ss - 1); } void mergeto(Node* &src, Node* &dest) { if (src->ch[0] != null) mergeto(src->ch[0], dest); if (src->ch[1] != null) mergeto(src->ch[1], dest); insert(dest, src->v); delete src; src = null; } void removetree(Node* &rt) { if (rt->ch[0] != null) removetree(rt->ch[0]); if (rt->ch[1] != null) removetree(rt->ch[1]); delete rt; rt = null; } struct Query{ char op; int x, p; Query(){} Query(char op, int x, int p) : op(op), x(x), p(p) {} }Q[maxc]; int Q_cnt; long long Q_sum; int cnt; int n, m; int val[maxn]; int from[maxm], to[maxm]; bool removed[maxm]; ///并查集相关 int fa[maxn]; void init_fa(int n) { for (int i = 0; i <= n; i++) fa[i] = i; } int find_set(int x) { return x == fa[x] ? fa[x] : fa[x] = find_set(fa[x]); } ///main相关 void add_edge(int i) { int x = from[i], y = to[i]; int fax = find_set(x), fay = find_set(y); if (fax != fay) { if (root[fax]->s < root[fay]->s) ///!!!注意 { fa[fax] = fay; mergeto(root[fax], root[fay]); } else { fa[fay] = fax; mergeto(root[fay], root[fax]); } } } void change(int i, int p) { int fai = find_set(i); remove(root[fai], val[i]); val[i] = p; insert(root[fai], val[i]); } void query(int i, int p) { int fai = find_set(i); Q_cnt++; Q_sum += kth(root[fai], p); } int main () { init_root(); int nc = 1; while (scanf("%d%d", &n, &m) != EOF && n + m) { init_fa(n); CLR(removed, 0); for (int i = 1; i <= n; i++) scanf("%d", &val[i]); for (int i = 1; i <= m; i++) scanf("%d%d", &from[i], &to[i]); char op; int x, p; cnt = 0; while (~scanf(" %c", &op) && op != 'E') { scanf("%d", &x); if (op == 'D') removed[x] = 1; else if (op == 'Q') scanf("%d", &p); else if (op == 'C') { scanf("%d", &p); swap(val[x], p); } Q[cnt++] = Query(op, x, p); } for (int i = 1; i <= n; i++) { if (root[i] != null) removetree(root[i]); root[i] = new Node(val[i], null); } for (int i = 1; i <= m; i++) { if (!removed[i]) add_edge(i); } Q_cnt = Q_sum = 0; for (int i = cnt - 1; i >= 0; i--) { if (Q[i].op == 'D') add_edge(Q[i].x); else if (Q[i].op == 'Q') query(Q[i].x, Q[i].p); else if (Q[i].op == 'C') change(Q[i].x, Q[i].p); } printf("Case %d: %.6lf\n", nc++, Q_sum / (double)Q_cnt); } return 0; }
相关文章推荐
- HDU 3726 Graph and Queries 离线处理 treap + 并查集
- LA 5031 Graph and Queries (离线处理 + Treap树维护名次)
- 【treap tree】 HDOJ 3726 && LA 5031 && UVA 1479 Graph and Queries
- HDU 3726 Graph and Queries (离线处理+splay tree)
- LA 5031 Graph and Queries (Treap + 并查集)
- hdu 3726 Graph and Queries 10天津赛区 离线算法+treap维护名次树
- LA 5031 Graph and Queries (【名次树(treap)】+【并查集】+【离线算法】)
- HDU 3726 Graph and Queries splay 离线 模拟
- HDU 3726 Graph and Queries (Treap)
- uva live 5031 Graph and Queries(Treap x 并查集)
- LA 5031 Graph and Queries —— Treap名次树
- LA 5031 Graph and Queries(Treap)
- HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题
- LA - 5031 - Graph and Queries(平衡树Treap)
- LA 5031 Graph and Queries Treap
- hdu 3726 Graph and Queries (Treap应用,名次树)
- HDU 3726 Graph and Queries Treap
- HDU 3726 Graph and Queries(treap)
- HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)
- UVALive 5031 Graph and Queries(离线,treap)