poj 2763 Housewife Wind(线段树+树剖)

来源:互联网 发布:清风算法辅助软件 编辑:程序博客网 时间:2024/05/20 23:56

将边的值转成深度大的端点的点值,然后就是树剖找lca通过dfs序把一条链的点映射到线段树上的区间去查询就好了。


需要注意的一点是,传入线段树的是dfs序,但是线段数的操作不需要去管dfs序,直接根据传进来的参数做就行了,这是一个容易写错的地方。


代码:

#include <iostream>#include <cstdio>#define MID int mid=(l+r)>>1;#define lson o<<1#define rson o<<1|1using namespace std;const int maxn=1e5+5;int val[maxn<<2];struct bian{    int u, v, w;}bmap[maxn];int n, m;int dfn[maxn], siz[maxn], son[maxn], FA[maxn], dis[maxn], dep[maxn], f[maxn];void update(int o, int l, int r, int x, int w){//    cout<<l<<" "<<r<<endl;    if(l==r && l==x)    {        val[o]=w;        return;    }    MID    if(x<=mid)update(lson, l, mid, x, w);    else update(rson, mid+1,r, x, w);    val[o]=val[lson]+val[rson];    return;}int query(int o, int l, int r, int ll, int rr){//    printf("%d %d %d %d %d\n", ll, rr,l, r, val[o]);    if(ll<=l && r<=rr)return val[o];    int res=0;    MID    if(ll<=mid)res+=query(lson, l, mid, ll, rr);    if(mid<rr)res+=query(rson, mid+1, r, ll, rr);    return res;}void build(int o, int l, int r){    if(l==r)    {//        printf("%d %d %d\n", l, dfn[l], dis[dfn[l]]);        val[o]=dis[l];        return;    }    MID    build(lson, l, mid);    build(rson, mid+1, r);    val[o]=val[lson]+val[rson];    return;}struct edg{    int to;    int w;    int nex;}edg[maxn*10];int head[maxn], cnt;void add(int u, int v, int w){    edg[cnt].to=v;    edg[cnt].w=w;    edg[cnt].nex=head[u];    head[u]=cnt++;}void dfs1(int x, int fa, int d){    siz[x]=1, son[x]=0, dep[x]=d;    int to, w, i;    for(i=head[x]; i!=-1; i=edg[i].nex)    {        to=edg[i].to, w=edg[i].w;        if(to!=fa)        {            f[to]=x;            dfs1(to, x, d+1);            siz[x]+=siz[to];            if(son[x]==0 || siz[to]>siz[son[x]])son[x]=to;        }    }    return;}int tot;void dfs2(int x, int fa, int F){    FA[x]=F, dfn[x]=++tot;    if(son[x]!=0)    {        dfs2(son[x], x, F);    }    int i, to;    for(i=head[x]; i!=-1; i=edg[i].nex)    {        to=edg[i].to;        if(to!=fa && to!=son[x])        {            dfs2(to, x, to);        }    }    return;}int pathquery(int x, int y){    int px=FA[x], py=FA[y], ans=0;    while(px!=py)    {//        printf("%d %d %d %d\n", x, y, px, py);        if(dep[px]>dep[py])        {            ans+=query(1, 1, n, dfn[px], dfn[x]);            x=f[px];            px=FA[x];        }        else        {            ans+=query(1, 1, n, dfn[py], dfn[y]);            y=f[py], py=FA[y];        }//        printf("%d %d %d %d\n", x, y, px, py);    }    if(x!=y)    {        if(dep[x]>dep[y])swap(x, y);//        cout<<dfn[x]<<" "<<dfn[y]<<endl;        ans+=query(1, 1, n, dfn[x]+1, dfn[y]);    }    return ans;}void init(){    for(int i=0; i<=n; i++)head[i]=-1;    cnt=0;    return;}int main(){    int q, s, i, j, w;//    while(~scanf("%d%d%d", &n, &q, &s))        cin>>n>>q>>s;    {    cnt=tot=0;    init();    for(i=1; i<=n-1; i++)    {        scanf("%d%d%d", &bmap[i].u, &bmap[i].v, &bmap[i].w);        add(bmap[i].u, bmap[i].v, bmap[i].w);        add(bmap[i].v, bmap[i].u, bmap[i].w);    }    dfs1(1, 0, 1);    dfs2(1, 0, 1);    for(i=1; i<=n-1; i++)    {        int u=dep[bmap[i].u]>dep[bmap[i].v]?bmap[i].u:bmap[i].v;        dis[dfn[u]]=bmap[i].w;    }//    for(i=2; i<=n; i++)printf("%d ", dis[dfn[i]]);printf("\n");    build(1, 1, n);//    for(i=1; i<=n; i++)//    {//        printf("%d %d %d %d\n", i, FA[i], son[i], f[i]);//    }    int last=s, x, y, op, u, v;    while(q--)    {        scanf("%d", &op);        if(op==0)        {            scanf("%d", &x);            printf("%d\n", pathquery(last, x));            last=x;        }        else        {            scanf("%d%d", &x, &y);            u=bmap[x].u, v=bmap[x].v;            int s=dep[u]>dep[v]?u:v;//            cout<<s<<endl;            update(1, 1, n, dfn[s], y);        }    }    }    return 0;}/*1320 11 2 12 4 14 10 12 5 15 11 111 12 11 3 13 7 13 6 16 8 18 9 19 13 11 12 50 13*/