【模板】【SPOJ375】树链剖分

来源:互联网 发布:网络教育本科统考 编辑:程序博客网 时间:2024/05/16 17:21

题目链接:https://vjudge.net/problem/SPOJ-QTREE
不错的Blog:
初学http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
练习https://vjudge.net/contest/28982
练习https://oi.abcdabcd987.com/summary-of-heavy-light-decomposition/
SPOJ375

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define getmid int m=(c[rt].l+c[rt].r)>>1using namespace std;///基于边权,修改单条边///查询路径边权最大值const int maxn=10010;int n;struct Edge{    int to,nxt;}e[maxn*2];struct segtree{    int l,r;    int Max;}c[maxn*4+5];int head[maxn],ecnt;int top[maxn];///top[v]表示v所在链的顶端结点int fa[maxn]; ///父节点int dep[maxn]; ///深度int siz[maxn]; ///siz[v]表示以v为根的子树的结点树int id[maxn];///id[v]表示v与其父节点的连边在线段树中的位置int real[maxn]; ///表示线段树中的某个位置对应的边的起始编号int son[maxn]; ///son[u]表示u的重儿子int dfn;int d[maxn][3];void init(){    ecnt=dfn=0;    memset(head,-1,sizeof(head));    memset(son,0,sizeof(son));}void add_edge(int u,int v){    e[++ecnt].nxt=head[u];    e[ecnt].to=v;    head[u]=ecnt;}void dfs1(int u,int f,int d){    int v;    dep[u]=d;    fa[u]=f;    siz[u]=1;    for(int i=head[u];i!=-1;i=e[i].nxt)        if((v=e[i].to)!=f)        {            dfs1(v,u,d+1);            siz[u]+=siz[v];            if(!son[u]||siz[son[u]]<siz[v])                son[u]=v;        }}void dfs2(int u,int tp){    int v;    top[u]=tp;    id[u]=++dfn;    real[id[u]]=u;    if(!son[u]) return;    dfs2(son[u],tp);    for(int i=head[u];i!=-1;i=e[i].nxt)        if((v=e[i].to)!=son[u]&&v!=fa[u])            dfs2(v,v);}void Build(int l,int r,int rt){    c[rt].l=l;    c[rt].r=r;    c[rt].Max=0;    if(l==r) return;    int m=(l+r)>>1;    Build(l,m,rt<<1);    Build(m+1,r,rt<<1|1);}void Pushup(int rt){    c[rt].Max=max(c[rt<<1].Max,c[rt<<1|1].Max);}void Update(int rt,int k,int val){    if(c[rt].l==k&&c[rt].r==k)    {        c[rt].Max=val;        return;    }    getmid;    if(k<=m) Update(rt<<1,k,val);    else     Update(rt<<1|1,k,val);    Pushup(rt);}int Query(int rt,int L,int R){    if(L<=c[rt].l&&R>=c[rt].r) return c[rt].Max;    getmid;    int ret=0;    if(L<=m) ret=max(ret,Query(rt<<1,L,R));    if(R>m)  ret=max(ret,Query(rt<<1|1,L,R));    return ret;}int ask_e(int u,int v){    int f1,f2,tmp=0;    while((f1=top[u])!=(f2=top[v]))    {        if(dep[f1]<dep[f2])        {            swap(f1,f2);            swap(u,v);        }        tmp=max(tmp,Query(1,id[f1],id[u]));        u=fa[f1];    }    if(u==v) return tmp;    if(dep[u]>dep[v]) swap(u,v);    return max(tmp,Query(1,id[son[u]],id[v]));}int main(){    int u,v;    int T;    cin>>T;    while(T--)    {        init();        cin>>n;        for(int i=1;i<=n-1;i++)        {            scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]);            add_edge(d[i][0],d[i][1]);            add_edge(d[i][1],d[i][0]);        }        dfs1(1,0,1);        dfs2(1,1);        Build(1,dfn,1);        for(int i=1;i<=n-1;i++)        {            if(dep[d[i][0]]>dep[d[i][1]])                swap(d[i][0],d[i][1]);            Update(1,id[d[i][1]],d[i][2]);          }        char s[10];        while(scanf("%s",s))        {            if(s[0]=='D') break;            scanf("%d%d",&u,&v);            if(s[0]=='Q')                printf("%d\n",ask_e(u,v));            else Update(1,id[d[u][1]],v);           }    }    return 0;}
原创粉丝点击