zoukankan      html  css  js  c++  java
  • HDU6393(环套树)

    题解: 很显然的是这个图必然是一个树上套一个简单环 我们考虑到只有树的情况 那么直接树链剖分+线段树就好了 如果多加一条边 qko告诉我可以类似基环树那样 取出这个环 那么我们可以对于一个询问分类 如果在一颗子树上我们可以直接查询即可 如果绕过环相连 那么可以取两点对应环上的点取min 加上两个点在不同子树中的路径长度即可

    #include <bits/stdc++.h>
    #define ll long long
    #define link(x) for(edge *j=h[x];j;j=j->next)
    const int MAXN=1e5+10;
    const int inf=1e9;
    using namespace std;
    struct FastIO
    {
        static const int S=200;
        int wpos;
        char wbuf[S];
        FastIO():wpos(0){}
        inline int xchar()
        {
            static char buf[S];
            static int len=0,pos=0;
            if(pos==len) pos=0,len=fread(buf,1,S,stdin);
            if(pos==len) exit(0);
            return buf[pos++];
        }
        inline int read()
        {
            int s=1,c=xchar(),x=0;
            while(c<=32) c=xchar();
            if(c=='-') s=-1,c=xchar();
            for(;'0'<=c&&c<='9';c=xchar()) x=x*10+c-'0';
            return x*s;
        }
        ~FastIO()
        {
            if(wpos) fwrite(wbuf,1,wpos,stdout),wpos=0;
        }
    }io;
    int n,m;
    int F[MAXN],f[MAXN],b[MAXN];
    int dep[MAXN],fa[MAXN],son[MAXN],num[MAXN],pos[MAXN],key[MAXN];
    bool vis[MAXN],vi[MAXN];
    int v1[MAXN];
    struct edge{int t,id;ll v;bool f;edge*next,*rev;}e[MAXN<<2],*h[MAXN],*o=e;
    void add(int x,int y,ll v,int p){o->v=v;o->t=y;o->id=p;o->next=h[x];h[x]=o++;}
    int __v[MAXN];
    int find1(int x){
        if(x==F[x])return x;
        else return F[x]=find1(F[x]);
    }
    int _x,tot,c[MAXN],_t;
    void _dfs(int x){
        __v[x]++;
        link(x)if(!j->f){
        j->f=j->rev->f=true;
        if(__v[j->t]){_t=j->t;c[++tot]=x;vis[x]=1;return;}
        else _dfs(j->t);
        if(_t){c[++tot]=x;vis[x]=1;break;}
        }
        if(_t==x)_t=0;
    }
    void dfs(int v,int pre,int deep){
        dep[v]=deep+1;fa[v]=pre;num[v]=1;
        link(v)if(j->t!=pre&&!vis[j->t]){
            F[j->t]=v;
            key[j->t]=j->v;
            pos[j->id]=j->t;
            dfs(j->t,v,deep+1);
            num[v]+=num[j->t];
            if(son[v]==-1||num[j->t]>num[son[v]])son[v]=j->t;        
        }
    }
    int p[MAXN],fp[MAXN],tp[MAXN],cnt;
    void dfs1(int v,int td){
        p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1)dfs1(son[v],td);
        link(v)if(j->t!=fa[v]&&j->t!=son[v]&&!vis[j->t])dfs1(j->t,j->t);
    }
    ll sum[MAXN<<2];
    void built(int rt,int l,int r){
        if(l==r){sum[rt]=key[fp[l]];return ;}
        int mid=(l+r)>>1;
        built(rt<<1,l,mid);
        built(rt<<1|1,mid+1,r);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    ll ans;
    void querty(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){ans+=sum[rt];return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
        if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
    }
    void update(int rt,int l,int r,int t,int vul){
        if(l==r){sum[rt]=vul;return ;}
        int mid=(l+r)>>1;
        if(t<=mid)update(rt<<1,l,mid,t,vul);
        else update(rt<<1|1,mid+1,r,t,vul);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    ll Sum(int u,int v){
        int uu=tp[u];int vv=tp[v];
        ll ans1=0;
        while(uu!=vv){
            if(dep[uu]<dep[vv]){swap(uu,vv);swap(u,v);}
            ans=0;querty(1,1,n,p[uu],p[u]);ans1+=ans;
            u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        //cout<<son[u]<<" "<<u<<" "<<v<<" "<<p[son[u]]<<" "<<p[v]<<" "<<ans1<<endl;
        if(u!=v)ans=0,querty(1,1,n,p[son[u]],p[v]),ans1+=ans;
        return ans1;
    }
    ll sum1[MAXN<<2];
    int get_id(int x){return x&(-x);}
    void update1(int x,int vul){
        //cout<<x<<" "<<vul<<endl;
        for(int i=x;i<=2*n;i+=get_id(i))sum1[i]+=vul;
    }
    ll querty1(int x){
        ll ans1=0;
        for(int i=x;i>0;i-=get_id(i))ans1+=sum1[i];
        return ans1;
    }
    int main(){
        //freopen("k.out","w",stdout);
        int _=io.read();//scanf("%d",&_);
        while(_--){
            n=io.read();m=io.read();memset(e,0,sizeof(e));memset(h,0,sizeof(h));o=e;
            memset(vis,0,sizeof(vis));memset(sum1,0,sizeof(sum1));memset(sum,0,sizeof(sum));
            memset(vi,0,sizeof(vi));
            memset(__v,0,sizeof(__v));
            for(int i=1;i<=n;i++)F[i]=i,son[i]=-1,pos[i]=n+1;
            int u,v,vul;tot=0;cnt=0;
            for(int i=1;i<=n;i++)u=io.read(),v=io.read(),vul=io.read(),add(u,v,vul,i),add(v,u,vul,i),h[u]->rev=h[v],h[v]->rev=h[u];
            for(int i=1;i<=n;i++)if(!__v[i])_dfs(i);
            for(int i=1;i<=tot;i++)v1[c[i]]=i;
            for(int i=1;i<=tot;i++)c[i+tot]=c[i],v1[c[i+tot]]=v1[c[i]];
            tot*=2;
            for(int k=1;k<=tot-1;k++)
                link(c[k])if(j->t==c[k+1])b[k+1]=j->v,pos[j->id]=min(pos[j->id],k+1),vi[j->id]=1;
            for(int k=1;k<=tot;k++)update1(k,b[k]);
            tot/=2;
            for(int i=1;i<=tot;i++){dfs(c[i],0,0);dfs1(c[i],c[i]);}
            //for(int i=1;i<=n;i++)cout<<key[i]<<" ";
            //    cout<<endl;
            built(1,1,n);
            int op,x,y;
            for(int i=1;i<=m;i++){
                op=io.read();x=io.read();y=io.read();
                if(op==0){
                    if(vi[x]){
                        x=pos[x];
                        update1(x,-1*b[x]);update1(x,y);
                        update1(x+tot,-1*b[x]);update1(x+tot,y);
                        b[x]=y;
                    }
                    else update(1,1,n,p[pos[x]],y);
                }
                else{
                    int t1=find1(x);int t2=find1(y);
                    if(t1==t2)printf("%lld
    ",Sum(x,y));
                    else{
                        ll ans1=Sum(x,t1);ans1+=Sum(y,t2);
                        t1=v1[t1];t2=v1[t2];
                        if(t1>t2)swap(t1,t2);
                        ans1+=min(querty1(t2)-querty1(t1),querty1(t1+tot)-querty1(t2));
                        printf("%lld
    ",ans1);
                    } 
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    区间K 大数查询
    最大最小公倍数
    吃糖果
    身份证号码升级
    威威猫系列之 吃鸡腿
    小Q系列之失恋
    查询7天之内的数据
    WebService案例 Spring boot+CXF开发WebService Demo
    开发过程中遇到问题
    oracle 自增序列 sequence
  • 原文地址:https://www.cnblogs.com/wang9897/p/9471879.html
Copyright © 2011-2022 走看看