POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新

来源:互联网 发布:智慧城市四大数据库 编辑:程序博客网 时间:2024/05/21 10:35

题目来源:POJ 2763 Housewife Wind

题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x

思路:树上两点u, v距离为d[u]+d[v]-2*d[LCA(u,v)] 现在d数组是变化的 对应每一条边的变化 他修改的是一个区间 用时间戳处理每个点管辖的区域 然后用线段树修改 线段树的叶子节点村的是根到每一个点的距离 求最近公共祖先没差别 只是堕落用线段树维护d数组

各种错误 4个小时 伤不起

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 200010;struct edge{int u, v, w, next;}edges[maxn*2], e[maxn];int E[maxn*2], H[maxn*2], I[maxn*2], L[maxn], R[maxn];int dp[maxn*2][40];int cnt, clock, dfn;int first[maxn];int a[maxn<<2];int b[maxn];int add[maxn<<2];int degree[maxn];int vis[maxn];void AddEdge(int u, int v, int w){edges[cnt].u = u;edges[cnt].v = v;edges[cnt].w = w;edges[cnt].next = first[u];first[u] = cnt++;edges[cnt].u = v;edges[cnt].v = u;edges[cnt].w = w;edges[cnt].next = first[v];first[v] = cnt++;}void dfs(int u, int fa, int dep){E[++clock] = u;H[clock] = dep;I[u] = clock;L[u] = ++dfn;b[dfn] = u;for(int i = first[u]; i != -1; i = edges[i].next){int v = edges[i].v;if(v == fa)continue;if(vis[v])continue;vis[v] = true;dfs(v, u, dep+1);E[++clock] = u;H[clock] = dep;}R[u] = dfn;}void RMQ_init(int n){for(int i = 1; i <= n; i++)dp[i][0] = i;for(int j = 1; (1<<j) <= n; j++)for(int i = 1; i+(1<<j)-1 <= n; i++){if(H[dp[i][j-1]] < H[dp[i+(1<<(j-1))][j-1]])dp[i][j] = dp[i][j-1];elsedp[i][j] = dp[i+(1<<(j-1))][j-1];}}int RMQ(int l, int r){l = I[l], r = I[r];if(l > r)swap(l, r);int len = r-l+1, k = 0;while((1<<k) <= len)k++;k--;if(H[dp[l][k]] < H[dp[r-(1<<k)+1][k]])return E[dp[l][k]];elsereturn E[dp[r-(1<<k)+1][k]];}void pushdown(int rt, int l, int r){int k = (r-l+1);if(add[rt]){a[rt<<1] += add[rt]*(k-(k>>1));a[rt<<1|1] += add[rt]*(k>>1);add[rt<<1] += add[rt];add[rt<<1|1] += add[rt];add[rt] = 0;}}void build(int l, int r, int rt){a[rt] = 0;add[rt] = 0;if(l == r)return;int m = (l + r) >> 1;build(l, m, rt<<1);build(m+1, r, rt<<1|1);}void update(int x, int y, int l, int r, int rt, int num){if(l == x && r == y){a[rt] += (r-l+1)*num;add[rt] += num;return;}pushdown(rt, l, r);int m = (l + r) >> 1;if(y <= m)update(x, y, l, m, rt<<1, num);else if(x > m)update(x, y, m+1, r, rt<<1|1, num);else{update(x, m, l, m, rt<<1, num);update(m+1, y, m+1, r, rt<<1|1, num);}a[rt] = a[rt<<1] + a[rt<<1|1];}int query(int x, int l, int r, int rt){if(l == r){return a[rt];}pushdown(rt, l, r);int m = (l + r) >> 1;int ans = 0;if(x <= m)ans = query(x, l, m, rt<<1);elseans = query(x, m+1, r, rt<<1|1);a[rt] = a[rt<<1] + a[rt<<1|1];return ans;}int main(){int cas = 1;int T;//scanf("%d", &T);int s, to, root, n, q;while(scanf("%d %d %d", &n, &q, &s) != EOF){memset(vis, 0, sizeof(vis));memset(first, -1, sizeof(first));memset(degree, 0, sizeof(degree));clock = cnt = dfn = 0;build(1, n, 1);//for(int i = 1; i <= n; i++)//scanf("%d", &b[i]);for(int i = 1; i < n; i++){int u, v, w;scanf("%d %d %d", &u, &v, &w);e[i].u = u;e[i].v = v;e[i].w = w;AddEdge(u, v, 0);degree[v]++;}for(int i = 1; i <= n; i++)if(!degree[i]){vis[i] = true;dfs(i, -1, 0);root = i;break;}RMQ_init(2*n-1);//puts("1");for(int i = 1; i < n; i++){int u = e[i].u;int v = e[i].v;int w = e[i].w;//printf("***%d %d\n", L[v], R[v]);if(L[u] < L[v])update(L[v], R[v], 1, n, 1, w);elseupdate(L[u], R[u], 1, n, 1, w);}while(q--){int x;scanf("%d", &x);if(!x){scanf("%d", &to);int d1 = query(L[s], 1, n, 1);int d2 = query(L[to], 1, n, 1);int lca = RMQ(s, to);int d3 = query(L[lca], 1, n, 1);//printf("***%d %d %d\n", d1, d2, d3);printf("%d\n", d1+d2-2*d3);//printf("%d\n", dfn);s = to;}else{int i, w;scanf("%d %d", &i, &w);int x = w - e[i].w;e[i].w = w;int v = e[i].v;int u = e[i].u;if(L[u] < L[v])update(L[v], R[v], 1, n, 1, x);elseupdate(L[u], R[u], 1, n, 1, x);}}}return 0;}



0 0