【树链剖分】 POJ 2763 Housewife Wind 边权

来源:互联网 发布:淘宝商品详情页多少钱 编辑:程序博客网 时间:2024/05/20 07:16

点击打开链接

题意:

操作0 X :求 当前位置到X 的长度

操作1 X Y :将第X条边长度更改为Y

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <string>#include <iostream>#include <algorithm>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include <set>#pragma comment(linker, "/STACK:1024000000,1024000000")#include <map>typedef long long LL;const int MAXN = 101000;//点数的最大值const int MAXM = 604000;//边数的最大值const int INF = 1152921504;const LL mod= 258280327;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1struct EDGENODE{    int to;    int w;    int next;}edges[MAXM];int head[MAXN],edge;inline void init(){    edge=0;    memset(head,-1,sizeof(head));}inline void addedge(int u,int v,int w){    edges[edge].w=w,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;    edges[edge].w=w,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;}int que[MAXN]; // 队列bool vis[MAXN]; // 访问标记int son[MAXN]; // 重儿子int idx[MAXN]; // 结点v在其路径中的编号int dep[MAXN]; // 结点v的深度int siz[MAXN]; // 以结点v为根的子树的结点个数int belong[MAXN]; // 结点v所属的路径编号int fa[MAXN]; // 结点v的父亲结点int top[MAXN]; // 编号为p的路径的顶端结点int len[MAXN]; // 路径p的长度int sump[MAXN]; // 路径p的编号int seg[MAXN]; // 结点v的父边在线段树中的位置int wei[MAXN]; // 结点v的父边的权值int l,r,ans,cnt;int n;char cmd[22];int num[MAXN];void split(){    memset(dep,-1,sizeof(dep));    l=0;    dep[ que[r=1]=1 ]=0; // 将根结点插入队列,并设深度为0    fa[1]=-1; // 默认 1 为根结点    wei[1]=0;    while (l<r){ // 第一遍搜索求出 fa,dep,wei        int u=que[++l];        vis[u]=false; // 顺便初始化vis        for (int i=head[u];i!=-1;i=edges[i].next){            int v=edges[i].to;            int w=edges[i].w;            if (dep[v]==-1){ // 未访问过的结点                dep[ que[++r]=v ]=dep[u]+1; // 将v插入队列并设深度为dep[u]+1                fa[v]=u; // v的父结点为u                wei[v]=w; // v的父边权值            }        }    }    cnt=0; // 重链编号    for (int i=n;i>0;i--){        int u=que[i],p=-1;        siz[u]=1;        son[u]=p;        for (int k=head[u];k!=-1;k=edges[k].next){            int v=edges[k].to;            if (vis[v]){ // 若v是u的子结点                siz[u]+=siz[v]; // 计数                if (p==-1||siz[v]>siz[p]){                    son[u]=v;                    p=v; // u的重儿子是v                }            }        }        if (p==-1){ // u是叶子结点            idx[u]=len[++cnt]=1; // 一个新的路径编号为cnt,u是路径中的第一个结点            belong[ top[cnt]=u ]=cnt; // u是顶端结点,且u属于路径cnt        }        else{ // u不是叶子结点            idx[u]=++len[ belong[u]=belong[p] ]; // u属于重儿子所在的链,链长+1,u是路径中第len个结点            top[ belong[u] ]=u; // u是顶端结点        }        vis[u]=true; // 访问标记    }}struct tree{    LL sum[MAXN<<2];    bool lazy[MAXN<<2];    void pushup(int rt)    {        sum[rt]=sum[rt<<1]+sum[rt<<1|1];    }    void build(int l,int r,int rt)    {        if(l==r)        {            sum[rt]=num[l];            return ;        }        int m=(l+r)>>1;        build(lson);        build(rson);        pushup(rt);    }    void update(int add,int flag,int l,int r,int rt)    {        if(l==r)        {            sum[rt]=add;            return ;        }        int m=(l+r)>>1;        if(flag<=m)            update(add,flag,lson);        else update(add,flag,rson);        pushup(rt);    }    LL query(int L,int R,int l,int r,int rt)    {        if(L<=l&&r<=R)        {            return sum[rt];        }        int m=(l+r)>>1,ans=0;        if(L<=m)            ans=ans+query(L,R,lson);        if(R>m)            ans=ans+query(L,R,rson);        return ans;    }}xixixi;LL find(int va,int vb){    int f1=top[belong[va]],f2=top[belong[vb]];    LL tmp=0;    while (f1!=f2){        if (dep[f1]<dep[f2]){            swap(f1,f2);            swap(va,vb);        }        tmp=tmp+xixixi.query(seg[f1],seg[va],1,n,1);        va=fa[f1];        f1=top[belong[va]];    }    if (va==vb) return tmp;    if (dep[va]>dep[vb]) swap(va,vb);    return tmp+xixixi.query(seg[son[va]],seg[vb],1,n,1);}int d[MAXN][3];int main(){    int m,now;    while (cin>>n>>m>>now)    {        init();        for (int i=1;i<n;i++){            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            d[i][0]=a;            d[i][1]=b;            d[i][2]=c;            addedge(a,b,c);        }        split();        sump[0]=0;        for (int i=1;i<=cnt;i++) sump[i]=sump[i-1]+len[i];        for (int i=1;i<=n;i++){            seg[i]=sump[ belong[i] ]-idx[i]+1;            num[ seg[i] ]=wei[i];        }        xixixi.build(1,n,1);        int x,y,z;        while (m--){        scanf("%d",&x);            if (x==0){                scanf("%d",&y);                printf("%I64d\n",find(y,now));                now=y;            }            else{                scanf("%d%d",&y,&z);                if (fa[d[y][1]]==d[y][0]) xixixi.update(z,seg[d[y][1]],1,n,1);                else xixixi.update(z,seg[d[y][0]],1,n,1);            }        }    }    return 0;}


0 0
原创粉丝点击