poj2763 Housewife Wind LCA

题目链接:

http://poj.org/problem?id=2763

题意:

一个无根树,给出主角一开始所在的位置S,然后下面q个操作,操作包括查询和修改操作,对于查询操作就是当前主角的位置到目的点的距离是多少,然后主角去到那里之后就在那里等待,下次查询的时候那里就是新的起点(所以sample中第二次查询为什么是3)。修改是修改第k条边的权值,边的编号就是输入的顺序。

思路:

求树上两点之间的距离,ans=dis[u]+dis[v]-dis[LCA(u,v)]*2;
求LCA这里是用的倍增的思想, 先让两个点跳到同一深度,然后两个点再同时往上跳,先跳大步。

还有别的方法求LCA,http://www.cnblogs.com/scau20110726/archive/2013/06/14/3135095.html 这个人的LCA挺好的【离线RMQ】。我觉得还是在线倍增比较好理解
对于修改,修改一条边,暴力更新dis这个数组,数据水,这样可以通过。
对于树链剖分的做法 蒟蒻不会

代码:

代码一:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 1e5+10;

struct node{
    int u,v,w,next;
}e[maxn*2];
int tot,dp[maxn][25],dep[maxn],head[maxn],dis[maxn];

void add(int u,int v,int w,int &k){
    e[k].u=u; e[k].v=v; e[k].w=w;
    e[k].next=head[u]; head[u]=k++;
    swap(u,v);
    e[k].u=u; e[k].v=v; e[k].w=w;
    e[k].next=head[u]; head[u]=k++;
}

void dfs(int u,int f){
    dep[u] = dep[f]+1;
    dp[u][0] = f;
    for(int i=head[u]; i!=-1; i=e[i].next){
        int v = e[i].v, w = e[i].w;
        if(v == f) continue;
        dis[v] = dis[u]+w;
        dfs(v,u);
    }
}

int LCA(int x,int y){
    if(dep[x] < dep[y]) swap(x,y);
    for(int i=20; i>=0; i--)
        if(dep[dp[x][i]]>=dep[y])
            x = dp[x][i];
    if(x == y) return x;
    for(int i=20; i>=0; i--)
        if(dep[dp[x][i]]==dep[dp[y][i]] && dp[x][i]!=dp[y][i])
            x = dp[x][i], y = dp[y][i];
    return dp[x][0];
}

void change(int u,int f,int val){
    dis[u] += val;
    for(int i=head[u]; i!=-1; i=e[i].next){
        if(f == e[i].v) continue;
        change(e[i].v,u,val);
    }
}

int main(){
    int n,q,s;
    while(cin>>n>>q>>s){
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i=1; i<n; i++){
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,tot);
        }
        dfs(1,0);
        for(int i=1; i<=20; i++)
            for(int j=1; j<=n; j++)
                dp[j][i] = dp[dp[j][i-1]][i-1];
        while(q--){
            int op = read();
            if(op == 0){
                int v = read();
                int ans = dis[s]+dis[v]-2*dis[LCA(s,v)];
                s = v;
                cout << ans << endl;
            }else{
                int p,y; scanf("%d%d",&p,&y);
                p = (p-1)*2;
                int u = e[p].u, v = e[p].v, w = e[p].w;
                int t1 = dep[u]<dep[v] ? v:u;
                int t2 = dep[u]<dep[v] ? u:v;
                e[p].w = e[p^1].w = y;
                change(t1,t2,y-w);
            }
        }
    }

    return 0;
}

代码二:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 1e5+10;

int n,q,s,tot;
int head[maxn];

struct edge{
    int u,v,w,next;
}e[maxn*2];

void add(int u,int v,int w,int &k){
    e[k].u=u; e[k].v=v; e[k].w=w;
    e[k].next=head[u]; head[u]=k++;
    swap(u,v);
    e[k].u=u; e[k].v=v; e[k].w=w;
    e[k].next=head[u]; head[u]=k++;
}

int ver[maxn*2],R[maxn*2],fir[maxn],_pow[25],dis[maxn],dp[maxn*2][25],dep[maxn];
bool vis[maxn];

void dfs(int u,int d){
    vis[u]=true; ver[++tot]=u, R[tot]=d, fir[u]=tot, dep[u]=d;
    for(int i=head[u]; i!=-1; i=e[i].next){
        int v=e[i].v,w=e[i].w;
        if(vis[v]) continue;
        dis[v] = dis[u]+w;
        dfs(v,d+1);
        ver[++tot]=u,R[tot]=d;
    }
}

void ST(int len){
    int k = (int)(log(len*1.0)/log(2.0));
    for(int i=0; i<=len; i++) dp[i][0] = i;
    for(int j=1; j<=k; j++){
        for(int i=1; i+(1<<j)-1<=len; i++){
            int a = dp[i][j-1], b = dp[i+_pow[j-1]][j-1];
            if(R[a] < R[b]) dp[i][j] = a;
            else dp[i][j] = b;
        }
    }
}
int RMQ(int x,int y){
    int k = (int)(log((y-x+1)*1.0)/log(2.0));
    int a = dp[x][k], b = dp[y-_pow[k]+1][k];
    if(R[a] < R[b]) return a;
    else return b;
}
int LCA(int x,int y){
    int a = fir[x], b = fir[y];
    if(a > b) swap(a,b);
    int res = RMQ(a,b);
    return ver[res];
}

void change(int u,int f,int x){
    dis[u] += x;
    for(int i=head[u]; i!=-1; i=e[i].next){
        int v = e[i].v;
        if(v == f) continue;
        change(v,u,x);
    }
}

int main(){
    for(int i=0; i<25; i++) _pow[i] = (1<<i);
    while(cin>>n>>q>>s){
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i=1; i<n; i++){
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            add(u,v,w,tot);
        }
        tot = 0;
        MS(dis); MS(vis);
        dfs(1,1);
        ST(tot);
        while(q--){
            int op = read();
            if(op == 0){
                int v = read();
                int ans = dis[s]+dis[v]-2*dis[LCA(s,v)];
                s = v;
                cout << ans << endl;
            }else{
                int x,y; scanf("%d%d",&x,&y);
                int t = (x-1)*2;
                int u = e[t].u, v = e[t].v, w = e[t].w;
                int t1 = dep[u]>dep[v] ? u:v;
                int t2 = dep[u]>dep[v] ? v:u;
                e[t].w = e[t^1].w = y;
                change(t1,t2,y-w);
            }
        }
    }

    return 0;
}
时间: 2024-08-07 14:51:02

poj2763 Housewife Wind LCA的相关文章

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

题目来源: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 <cs

LCA+线段树/树状数组 POJ2763 Housewife Wind

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11250   Accepted: 3111 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beauti

POJ 2763 Housewife Wind LCA基础题

Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 7047   Accepted: 1784 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beautiful huts. There

POJ - 2763 Housewife Wind(LCA+暴力)

题目大意:给出N个点,M条边和一个人的起始位置,然后给出一系列操作 操作A: 0 u 询问这个人走到u这个位置需要几分钟 操作B: 1 i w,将第i条边的权值改成w 解题思路:第一个操作比较简单,第二个操作的话也不难. 在dfs纪录结点出现的顺序的时候,顺便记录一下每个点的pre,为第二个操作做准备. 执行第二个操作时,先把本来的边改变一下,再用一次dfs将该边以下的边全部该变一下就好了,这时pre数组就有用了,因为它标记了哪几个点是和该边有关的 #include <cstdio> #inc

POJ2763 Housewife Wind(DFS序)

题目:单边修改,树链查询. 这题是边权,不是点权,不过也可以看作是点权. 然后其实就和BZOJ2819一样. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 111111 6 struct Edge{ 7 int u,v,w,nxt; 8 }edge[MAXN<<1]; 9 int n,head[MAXN],N

POJ2763 Housewife Wind

树链剖分边更新,线段树单点更新,区间查询 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdlib> 5 using namespace std; 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 const int maxn = 100005; 9 int siz

POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beauti

POJ 2763 Housewife Wind(树链剖分)(线段树单点修改)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 10378   Accepted: 2886 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beauti

POJ 2763 Housewife Wind

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 8618   Accepted: 2291 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beautif