|poj 2763|LCA, 树状数组|或者|树链剖分, 线段树|Housewife Wind
来源:互联网 发布:中国电信2g网络制式 编辑:程序博客网 时间:2024/05/20 21:46
poj 2763
LCA+树状数组/线段树。
首先本题大致一看就是一个LCA,但是本题有操作更改某边的权,这样会使得原本的far数组变化,不难发现,更改边权后影响该边下面所有点的答案。此时可以在LCA的DFS预处理时求出DFS序列(即时间戳),找到每个点管辖的范围,修改边权相当于修改该边连接的两个点深度深的那个点所管辖的范围,此时修改可以用暴力,但是由于far数组与LCA本身查询无关,我们可以用数据结构进行维护far数组,树状数组/线段树都可以
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define ms(i, j) memset(i, j, sizeof i)#define FN2 "poj2763" using namespace std;const int MAXN = 100000 + 5, logs = 17;int n, q, s, wi[MAXN], deep[MAXN], pre[MAXN][logs+1], far[MAXN], ll[MAXN], rr[MAXN], cnt, a[MAXN], b[MAXN], Sc[MAXN];vector<int> G[MAXN];//bitint lowbit(int x){ return x&(-x);}void update(int x, int v){ for (int i=x;i<=n;i+=lowbit(i)) { far[i] += v; }}int dist(int x){ int ret = 0; for (int i=x;i>0;i-=lowbit(i)) { ret += far[i]; } return ret;}//lcavoid dfs(int x, int p){ ll[x] = ++cnt; Sc[x] = cnt; pre[x][0] = p; deep[x] = deep[p] + 1; for (int i=1;i<=logs;i++) pre[x][i] = pre[pre[x][i-1]][i-1]; for (int i=0;i<G[x].size();i++) { int u = G[x][i]; if (u!=p) { dfs(u, x); } } rr[x] = cnt;}int lca(int x, int y){ if (deep[x]>deep[y]) swap(x, y); int del = deep[y] - deep[x]; for (int i=logs;i>=0;i--) if ((del>>i) &1) y = pre[y][i]; if (x==y) return x; for (int i=logs;i>=0;i--) if (pre[x][i]!=pre[y][i]) x = pre[x][i], y = pre[y][i]; return pre[x][0];}//provoid init(){ cnt = 0; for (int i=1;i<=n;i++) { G[i].clear(), deep[i] = far[i] = ll[i] = rr[i] = 0; for (int j=0;j<=logs;j++) pre[i][j] = 0; } for (int i=1;i<n;i++) { scanf("%d%d%d", &a[i], &b[i], &wi[i]); G[a[i]].push_back(b[i]); G[b[i]].push_back(a[i]); }}void solve(){ dfs(1, 0); int db4; for (int i=1;i<n;i++) { int x = a[i], y = b[i]; if (deep[x]>deep[y]) swap(x, y); update(ll[y], wi[i]); update(rr[y]+1, -wi[i]); } for (int i=1;i<=q;i++) { int opr; scanf("%d", &opr); if (opr==0) { int u; scanf("%d", &u); printf("%d\n", dist(Sc[s])+dist(Sc[u])-2*dist(Sc[lca(s, u)]));//一定要找s,u在DFS序列中的位置 s = u; } else { int x, w; scanf("%d%d", &x, &w); int y = (deep[a[x]]>deep[b[x]]) ? a[x] : b[x]; update(ll[y], w-wi[x]); update(rr[y]+1, wi[x]-w); wi[x] += w-wi[x];//边权点权分清楚 } }}int main(){ #ifndef ONLINE_JUDGE freopen(FN2".in","r",stdin); freopen(FN2".out","w",stdout); #endif while (scanf("%d%d%d", &n, &q, &s)==3) { init(); solve(); } return 0;}
树链剖分+线段树也可以。(此题卡vector,这迫使我试了一次链式前向星)
#include<cstdio>#include<cstring>#include<algorithm>#define fo(i, j, k) for (i=(j);i<=(k);i++)#define fd(i, k, j) for (i=(k);i>=(j);i--)#define rd(a) scanf("%d", &a)#define rd2(a, b) scanf("%d%d", &a, &b)#define rd3(a, b, c) scanf("%d%d%d", &a, &b, &c)#define ms(i, j) memset(i, j, sizeof i)#define FN2 "poj2763" using namespace std;const int MAXN = 100001 + 5;struct data{int to, next;}e[MAXN*2];int head[MAXN],cnt; int n, q, s, ai[MAXN], bi[MAXN], wi[MAXN];int dep[MAXN], fa[MAXN], son[MAXN], siz[MAXN], p[MAXN], top[MAXN], pre;void ins(int u, int v) {cnt++, e[cnt].to = v, e[cnt].next = head[u],head[u] = cnt;}void dfs1(int u, int p) { int i; dep[u] = dep[p] + 1, fa[u] = p, siz[u] = 1; for (i=head[u];i!=-1;i=e[i].next) { int v = e[i].to; if (v!=p) { dfs1(v, u); siz[u] += siz[v]; if (son[u]==-1||siz[son[u]]<siz[v]) son[u] = v; } }}void dfs2(int u, int chain) { int i; top[u] = chain, p[u] = ++pre; if (son[u]!=-1) { dfs2(son[u], chain); for (i=head[u];i!=-1;i=e[i].next) { int v = e[i].to; if (v!=fa[u]&&v!=son[u]) dfs2(v, v); } }}int sumv[MAXN*4];void pushup(int o) { int lc = o*2, rc = o*2+1; sumv[o] = sumv[lc] + sumv[rc];}void update(int o, int l, int r, int x, int y, int v) { int lc = o*2, rc = o*2+1, M = (l+r)/2; if (x<=l&&r<=y) { sumv[o] = v; return ; } if (x<=M) update(lc, l, M, x, y, v); if (M<y) update(rc, M+1, r, x, y, v); pushup(o);}int query(int o, int l, int r, int x, int y) { int lc = o*2, rc = o*2+1, M = (l+r)/2, ret = 0; if (x<=l&&r<=y) { return sumv[o]; } if (x<=M) ret += query(lc, l, M, x, y); if (M<y) ret += query(rc, M+1, r, x, y); return ret;}int findSUM(int u, int v) { int f1 = top[u], f2 = top[v], ret = 0; while (f1!=f2) { if (dep[f1]<dep[f2]) swap(f1, f2), swap(u, v); ret += query(1,1,n,p[f1],p[u]); u = fa[f1]; f1 = top[u]; } if (dep[u]<dep[v]) swap(u, v); return ret + query(1,1,n,p[v]+1,p[u]);}void init() { int i; pre = 0; fo (i, 1, n) dep[i] = fa[i] = siz[i] = p[i] = top[i] = 0, son[i] = -1, head[i] = e[i].next = -1; fo (i, 1, n*4) sumv[i] = 0; fo (i, 1, n-1) { rd3(ai[i], bi[i], wi[i]); ins(ai[i], bi[i]), ins(bi[i], ai[i]); } dfs1(1, 0), dfs2(1, 1); fo (i, 1, n-1) { int a1 = ai[i], b1 = bi[i]; if (dep[a1]>dep[b1]) update(1, 1, n, p[a1], p[a1], wi[i]); if (dep[a1]<dep[b1]) update(1, 1, n, p[b1], p[b1], wi[i]); }}void solve() { int i; fo (i, 1, q) { int opt; rd(opt); if (opt==0) { int u; rd(u); printf("%d\n", findSUM(u, s)); s = u; } else { int u, w; rd2(u, w); int a1 = ai[u], b1 = bi[u]; if (dep[a1]>dep[b1]) update(1, 1, n, p[a1], p[a1], w); if (dep[a1]<dep[b1]) update(1, 1, n, p[b1], p[b1], w); } }}int main() { #ifndef ONLINE_JUDGE freopen(FN2".in","r",stdin);freopen(FN2".out","w",stdout); #endif while (rd3(n, q, s)==3) init(), solve(); return 0;}
0 0
- |poj 2763|LCA, 树状数组|或者|树链剖分, 线段树|Housewife Wind
- POJ 2763 Housewife Wind (LCA + 树状数组)
- POJ 2763 Housewife Wind (LCA+线段树)
- LCA+线段树/树状数组 POJ2763 Housewife Wind
- POJ 2763 Housewife Wind (LCA+树状数组)
- poj 2763 Housewife Wind (LCA转RMQ+树状数组)
- poj 2763 Housewife Wind 【LCA 与 树状数组】
- POJ 2763 Housewife Wind (树链剖分+线段树)
- poj 2763 Housewife Wind(RQM+树状数组)
- POJ 2763 Housewife Wind [树链剖分(边权)+树状数组]【数据结构】
- poj 2763 Housewife Wind 树链剖分+LCA
- poj 2763 Housewife Wind 【LCA or 树链剖分】
- 【POJ 2763】Housewife Wind【LCA】
- poj 2763 Housewife Wind(线段树+树剖)
- poj 2763 Housewife Wind(LCA经典题目 处理树链)
- POJ - 2763 Housewife Wind(LCA+暴力)
- POJ 2763Housewife Wind(LCA)
- POJ-2763 Housewife Wind (树链剖分 入门题 树状数组 单点修改 区间查询)
- Centos 7安装配置MySQL
- learn the python in hard way习题36~39的附加习题
- ros中odometry数据生成方式与分发去向
- 1.OP-TEE代码结构
- 刚体变换(Rigid Transformation)
- |poj 2763|LCA, 树状数组|或者|树链剖分, 线段树|Housewife Wind
- Leetcode 231 and 342. Power of 2, Power of 4
- 使用codematic开发一个畅想汇项目,结课作业
- 树莓派简介与应用
- 物理地址
- PAT_1044. Shopping in Mars
- 240. Search a 2D Matrix II 题解
- 【BZOJ2463】 [中山市选2009]谁能赢呢?
- 蓝桥杯 历届试题 高僧斗法 (stairNim博弈)