hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
来源:互联网 发布:知乎 恶魔的奶爸 编辑:程序博客网 时间:2024/05/01 18:36
Treap树入门练习题目,此题主要来练习Treap的操作
此题也是刘汝佳 大白书,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_pairtypedef 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_pairtypedef 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 , 天津 2010, LA 5031,并查集,Treap,离线处理
- HDU 3726 Graph and Queries 离线处理 treap + 并查集
- LA 5031 Graph and Queries (【名次树(treap)】+【并查集】+【离线算法】)
- HDU 3276 Graph and Queries [离线+并查集+treap]
- LA 5031 Graph and Queries (Treap + 并查集)
- LA 5031 Graph and Queries (离线处理 + Treap树维护名次)
- UvaLive 5031 Graph and Queries(Treap+并查集)
- LA 5031 Graph and Queries Treap
- LA 5031 Graph and Queries(Treap)
- UVALive 5031 Graph and Queries(离线,treap)
- uva live 5031 Graph and Queries(Treap x 并查集)
- HDU 3726 Graph and Queries (Treap)
- HDU 3726 Graph and Queries treap树
- HDU 3726 Graph and Queries(treap)
- LA - 5031 - Graph and Queries(平衡树Treap)
- 【treap tree】 HDOJ 3726 && LA 5031 && UVA 1479 Graph and Queries
- LA 5031 Graph and Queries【名次树】【离线算法】
- UVA 1479 Graph and Queries(Treap:名次树+并查集)
- 如何在Notes email里播放视频
- C#时间
- IBM Domino 9.0.1和ODS 52
- 自然语言处理宗论 正则表达式与自动机
- Android官方提供的支持不同屏幕大小的全部方法
- hdu 3726 Graph and Queries , 天津 2010, LA 5031,并查集,Treap,离线处理
- gmu
- 自然语言处理宗论 导论
- android textview drawableleft使用时遇到的问题
- log4j.properties配置与加载
- 使用ATL建立支持IClassFactory2的COM组件
- 关于线程池结构以及互斥锁的运行机制
- 图像对机器翻译的重要意义
- 【11月18 日】2013年社交商务技术创新日(北京站)