BZOJ 2816 [ZJOI2012]网络
2012-06-02 17:11
330 查看
题目大意:
一个无向图, 每条边有颜色, 颜色不超过10种. 从一个点出发的同色边不超过2条, 且不存在同色环. 操作有修改一个点的权值, 修改某条边的颜色, 询问两点之间由某种颜色构成的简单路径上权值最大值.
简要分析:
围观这道题...发现相同颜色的构成了一坨链, 操作就是连接两条链, 断开一条链, 询问同一链上两点间最大值.
赤裸裸的数据结构题. 用Splay维护所有链, 可以很方便的断开和连接. 注意连接的时候可能会需要把其中一根链反转, 这个是经典操作, 打标记就可以了.
一个trick就是询问的两个点相同...我的程序要特判...晕...加上读入优化后速度还可以. 另外这题不是链而是树的话也是可以捉的...只不过要用LCT了...
哦, 题面可以去noi吧的自助资源站找.
代码实现:
View Code
一个无向图, 每条边有颜色, 颜色不超过10种. 从一个点出发的同色边不超过2条, 且不存在同色环. 操作有修改一个点的权值, 修改某条边的颜色, 询问两点之间由某种颜色构成的简单路径上权值最大值.
简要分析:
围观这道题...发现相同颜色的构成了一坨链, 操作就是连接两条链, 断开一条链, 询问同一链上两点间最大值.
赤裸裸的数据结构题. 用Splay维护所有链, 可以很方便的断开和连接. 注意连接的时候可能会需要把其中一根链反转, 这个是经典操作, 打标记就可以了.
一个trick就是询问的两个点相同...我的程序要特判...晕...加上读入优化后速度还可以. 另外这题不是链而是树的话也是可以捉的...只不过要用LCT了...
哦, 题面可以去noi吧的自助资源站找.
代码实现:
View Code
#include <cstdio> #include <cstring> #include <utility> #include <map> #include <algorithm> using std::pair; using std::make_pair; using std::map; using std::max; using std::min; using std::swap; typedef pair<int, int> Edge; map<Edge, int> col_idx; const int kMaxN = 10000, kMaxM = 200000, kMaxC = 10; int n, m, col_kind, q, w[kMaxN]; int cnt, begin[kMaxN], end[kMaxM], next[kMaxM], col[kMaxM]; int col_cnt[kMaxN][kMaxC]; bool col_vis[kMaxN][kMaxC]; #undef NULL #define NULL Node::nil struct Info { int v; Info() : v(0) {} Info(int v_) : v(v_) {} }; inline Info operator + (const Info &a, const Info &b) { return Info(max(a.v, b.v)); } struct Mark { bool rev; Mark() : rev(false) {} Mark(bool rev_) : rev(rev_) {} }; struct Node { Info ori, acc; Mark mark; Node *son[2], *par; Node() { son[0] = son[1] = par = NULL; } void update() { acc = son[0]->acc + ori + son[1]->acc; } static Node nil_ins, *nil; } node_pool[kMaxN * kMaxC], *node[kMaxN][kMaxC]; Node Node::nil_ins; Node *Node::nil = &nil_ins; void DoPush(Node *pos, const Mark &mark) { if (pos != NULL && mark.rev) { pos->mark.rev ^= 1; swap(pos->son[0], pos->son[1]); } } void Push(Node *pos) { if (pos != NULL && pos->mark.rev) { DoPush(pos->son[0], pos->mark.rev); DoPush(pos->son[1], pos->mark.rev); pos->mark.rev = false; } } void Rot(Node *pos, bool t) { Node *tptr = pos->son[t], *tmp = NULL; pos->son[t] = tptr->son[!t]; if ((tmp = tptr->son[!t]) != NULL) tmp->par = pos; tptr->son[!t] = pos; if ((tmp = pos->par) != NULL) tmp->son[tmp->son[1] == pos] = tptr; pos->par = tptr; tptr->par = tmp; } void PushTo(Node *pos) { static Node *stack[kMaxN]; static int stop; stop = 0; while (pos != NULL) { stack[stop ++] = pos; pos = pos->par; } while (stop) { Push(stack[stop - 1]); -- stop; } } void Splay(Node *pos, Node *des = NULL) { PushTo(pos); Node register *ngra, *npar; bool register d1, d2; while (pos != des && (npar = pos->par) != des) { ngra = npar->par; if (ngra == des) Rot(npar, npar->son[1] == pos), npar->update(); else { if ((d1 = (ngra->son[1] == npar)) == (d2 = (npar->son[1] == pos))) Rot(ngra, d1), Rot(npar, d2); else Rot(npar, d2), Rot(ngra, d1); ngra->update(), npar->update(); } } pos->update(); } void AddEdge(int u, int v, int c) { next[cnt] = begin[u]; begin[u] = cnt; end[cnt] = v; col[cnt ++] = c; } Node *BuildTree(int l, int r, Node *npar, int *q, int c) { if (l > r) return NULL; int mid = (l + r) >> 1; Node *res = node[q[mid]][c]; res->par = npar; res->ori.v = res->acc.v = w[q[mid]]; res->son[0] = BuildTree(l, mid - 1, res, q, c); res->son[1] = BuildTree(mid + 1, r, res, q, c); res->update(); return res; } void FindChain(int u, int c) { static int q[kMaxN], qh, qt; qh = qt = 0; q[qt ++] = u; col_vis[u][c] = true; while (qh < qt) { int u = q[qh ++]; for (int now = begin[u], v; now != -1; now = next[now]) if (col[now] == c && !col_vis[v = end[now]][c]) { col_vis[v][c] = true; q[qt ++] = v; break; } } BuildTree(0, qt - 1, NULL, q, c); } bool IsConnectedByAColor(Node *u, Node *v) { Splay(u), Splay(v); return (u->par != NULL); } void Split(Node *u, Node *v) { Splay(u), Splay(v, u); v->par = NULL; u->son[u->son[1] == v] = NULL; u->update(); } void Merge(Node *u, Node *v) { Splay(u), Splay(v); if (u->son[1] == NULL && v->son[0] == NULL) u->son[1] = v; else if (u->son[0] == NULL && v->son[1] == NULL) u->son[0] = v; else if (u->son[0] == NULL) { DoPush(u, Mark(true)); Push(u); u->son[1] = v; } else { DoPush(u, Mark(true)); Push(u); u->son[0] = v; } v->par = u; u->update(); } int AskMax(Node *u, Node *v) { Splay(u), Splay(v, u); bool t = (u->son[1] == v); return (u->son[t]->son[!t]->acc + u->ori + v->ori).v; } inline bool IsConnectedByAColor(int u, int v, int c) { return IsConnectedByAColor(node[u][c], node[v][c]); } inline void Split(int u, int v, int c) { Split(node[u][c], node[v][c]); } inline void Merge(int u, int v, int c) { Merge(node[u][c], node[v][c]); } inline int AskMax(int u, int v, int c) { return AskMax(node[u][c], node[v][c]); } int main() { memset(begin, -1, sizeof(begin)); scanf("%d%d%d%d", &n, &m, &col_kind, &q); for (int i = 0; i < n; ++ i) for (int j = 0; j < col_kind; ++ j) node[i][j] = &node_pool[i * col_kind + j]; for (int i = 0; i < n; ++ i) scanf("%d", &w[i]); for (int u, v, c; m --; ) { scanf("%d%d%d", &u, &v, &c); -- u, -- v; AddEdge(u, v, c); AddEdge(v, u, c); ++ col_cnt[u][c]; ++ col_cnt[v][c]; col_idx[make_pair(min(u, v), max(u, v))] = c; } for (int i = 0; i < col_kind; ++ i) for (int j = 0; j < n; ++ j) if (col_cnt[j][i] == 1 && !col_vis[j][i]) FindChain(j, i); for (int cmd, u, v, c; q --; ) { scanf("%d", &cmd); if (cmd == 0) { scanf("%d%d", &u, &v); -- u; w[u] = v; for (int i = 0; i < col_kind; ++ i) { Splay(node[u][i]); node[u][i]->ori.v = node[u][i]->acc.v = v; node[u][i]->update(); } } else if (cmd == 1) { scanf("%d%d%d", &u, &v, &c); -- u, -- v; if (u > v) swap(u, v); if (!col_idx.count(make_pair(u, v))) printf("No such edge.\n"); else { int ori_c = col_idx[make_pair(u, v)]; if (c == ori_c) printf("Success.\n"); else if (col_cnt[u][c] + 1 > 2 || col_cnt[v][c] + 1 > 2) printf("Error 1.\n"); else if (IsConnectedByAColor(u, v, c)) printf("Error 2.\n"); else { Split(u, v, ori_c); Merge(u, v, c); printf("Success.\n"); -- col_cnt[u][ori_c]; -- col_cnt[v][ori_c]; ++ col_cnt[u][c]; ++ col_cnt[v][c]; col_idx[make_pair(u, v)] = c; } } } else { scanf("%d%d%d", &c, &u, &v); -- u, -- v; if (u == v) printf("%d\n", w[u]); else if (!IsConnectedByAColor(u, v, c)) printf("-1\n"); else printf("%d\n", AskMax(u, v, c)); } } return 0; }
相关文章推荐
- [BZOJ2816][ZJOI2012]网络(lct+map)
- [bzoj2816][ZJOI2012]网络(LCT,splay)
- bzoj 2816: [ZJOI2012]网络(splay)
- 【bzoj2816】[ZJOI2012]网络 LCT
- [bzoj2816][ZJOI2012]网络
- bzoj2816 [ZJOI2012]网络(lct)
- BZOJ.2816.[ZJOI2012]网络(LCT)
- BZOJ2816:[ZJOI2012]网络——题解
- 【bzoj2816】【ZJOI2012】【网络】【lct】
- [ZJOI2012][bzoj 2816] 网络 network [LCT]
- 【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)
- [BZOJ2816][ZJOI2012]网络(LCT)
- [BZOJ2816][ZJOI2012]网络-Link Cut Tree
- AC日记——[ZJOI2012]网络 bzoj 2816
- bzoj2816.。。。。zjoi2012网络
- bzoj千题计划223:bzoj2816: [ZJOI2012]网络
- BZOJ 2816 [ZJOI2012]网络 Link Cut Tree
- bzoj2816 [ZJOI2012]网络
- bzoj2816 [ZJOI2012]网络
- [BZOJ2816][ZJOI2012]网络(LCT)