POJ 2763 Housewife Wind

n个结点的树,两种操作:更新一条边的权值,询问两点间的路径的权值和。

典型的树链剖分。

用线段树写了,不知道为嘛TLE。先贴在这儿,待以后研究。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
#define maxn 100050
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
struct Edge
{
    int v,next;
} edge[maxn<<1];
int tree[maxn],tot,cnt,a,b,e[maxn][3],head[maxn], dep[maxn], id[maxn], fa[maxn], top[maxn], son[maxn], num[maxn];
void add(int a, int b)
{
    edge[++cnt].v = b;
    edge[cnt].next = head[a];
    head[a] = cnt;
}
void dfs(int v)
{
    num[v] = 1,son[v] = 0;
    for (int i = head[v]; i > 0; i = edge[i].next)
        if (edge[i].v != fa[v])
        {
            fa[edge[i].v] = v;
            dep[edge[i].v] = dep[v]+1;
            dfs(edge[i].v);
            if (num[edge[i].v] > num[son[v]]) son[v] = edge[i].v;
            num[v] += num[edge[i].v];
        }
}
void dfs2(int v, int tp)
{
    id[v] = tot++;
    top[v] = tp;
    if (son[v] != 0) dfs2(son[v], top[v]);
    for (int i = head[v]; i > 0; i = edge[i].next)
        if (edge[i].v != son[v] && edge[i].v != fa[v])
            dfs2(edge[i].v, edge[i].v);
}

void update(int i, int l, int r, int k, int x)
{
    if (l == r) { tree[i] = x; return;}
    int m = (l + r)>>1;
    if(k<=m) update(lson,k,x);
    else update(rson,k,x);
    tree[i] = tree[i<<1]+tree[i<<1|1];
}

int query(int i, int l, int r, int L, int R)
{
    if (L<= l && r <= R) return tree[i];
    int m = (l + r)>>1,ans=0;
    if(L<=m) ans+=query(lson,L,R);
    if(R>m) ans+=query(rson,L,R);
    return ans;
}
int find(int va, int vb)
{
    int f1 = top[va], f2 = top[vb], tmp = 0;
    while (f1 != f2)
    {
        if (dep[f1] < dep[f2])
        {
            swap(f1, f2);
            swap(va, vb);
        }
        tmp+=query(1, 1, tot, id[f1], id[va]);
        va = fa[f1];
        f1 = top[va];
    }
    if (va == vb) return tmp;
    if (dep[va] > dep[vb]) swap(va, vb);
    tmp+=query(1, 1, tot, id[son[va]], id[vb]);
    return tmp;
}
int main()
{
    int q,s,n;
    scanf("%d%d%d", &n,&q,&s);

        fa[1] = tot = dep[1] = cnt = 0;
        memset(num, 0, sizeof(num));
        memset(head, 0, sizeof(head));
        memset(tree, 0, sizeof(tree));
        for (int i = 1; i < n; i++)
        {
            scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]);
            add(e[i][0],e[i][1]);
            add(e[i][1],e[i][0]);
        }
        dfs(1);
        dfs2(1,1);
        for (int i = 1; i < n; i++)
        {
            if (dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]);
            update(1, 1, tot, id[e[i][1]], e[i][2]);
        }
        while(q--)
        {
            int c;
            scanf("%d",&c);
            if(c)
            {
                scanf("%d%d",&a,&b);
                update(1,1,tot,id[e[a][1]],b);
            }
            else
            {
                scanf("%d",&a);
                printf("%d\n",find(s,a));
                s=a;
            }
        }

    return 0;
}


后面改用树状数组写了:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define  N 100005
#define low(x) ((x)&-(x))
int n,q,s,head[N],e[N<<1],next[N<<1],tot,fa[N],num[N],son[N],dep[N],c[N],pos[N],top[N],ID[N],w[N],t;

void add(int u,int v) {
	e[++tot]=v;
	next[tot]=head[u];
	head[u]=tot;
}

void dfs(int u) {
	num[u]=1,son[u]=0;
	for(int i=head[u];i;i=next[i]) {
		int v=e[i];
		if(v!=fa[u]) {
		fa[v]=u,dep[v]=dep[u]+1;
		dfs(v);
		num[u]+=num[v];
		if(num[son[u]]<num[v]) son[u]=v;
		}
	}
}

void dfs2(int u,int tp) {
	pos[u]=t++,top[u]=tp;
	if(son[u]) dfs2(son[u],tp);
	for(int i=head[u];i;i=next[i]) {
		int v=e[i];
		if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
		ID[(i+1)/2]=pos[v];
	}
}

 void update(int x,int d) {
	for(;x<=n;x+=low(x)) c[x]+=d;
}

int sum(int x) {
    int ans=0;
	for(;x>0;x-=low(x))  ans+=c[x];
	return ans;
}

int query(int a,int b) {
	int f1=top[a],f2=top[b],ans=0;
	while(f1!=f2) {
		if(dep[f1]<dep[f2]) {
			swap(a,b);
			swap(f1,f2);
		}
		ans+=sum(pos[a])-sum(pos[f1]-1);
		a=fa[f1];
		f1=top[a];
	}
	if(a!=b) {
		if(dep[a]>dep[b]) swap(a,b);
		ans+=sum(pos[b])-sum(pos[a]);
	}
	return ans;
}

int main() {
	scanf("%d%d%d",&n,&q,&s);
	for(int i=1,u,v;i<n;i++) {
		scanf("%d%d%d",&u,&v,&w[i]);
		add(u,v);
		add(v,u);
	}
	dfs(1),dfs2(1,1);
	for(int i=1;i<n;i++)  update(ID[i],w[i]);
	while(q--) {
		int op,x,y;
		scanf("%d",&op);
		if(op) {
            scanf("%d%d",&x,&y);
			update(ID[x],y-w[x]);
			w[x]=y;
		} else {
			scanf("%d",&x);
			printf("%d\n",query(s,x));
			s=x;
		}
	}
	return 0;
}


你可能感兴趣的:(POJ 2763 Housewife Wind)