• hdu 5044 树区间操作最后输出/ lca+dfs


    题意:一棵树,俩种操作:1 有路径上的全部点加vi,2全部边加vi。

     先离线求出全部询问的lca,再遍历询问一次,点+vi,lca-2*vi ,最后dfs从叶子扫上来一次,最后再祖先点补上就可以。用了输入挂。

    复杂度(n+m).

    #pragma comment(linker,"/STACK:10240000000000,10240000000000")
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    const int maxv=100005,maxe=200015;
    int head[maxv];int nume=0;long long e[maxe][3];
    void inline adde(int i,int j)       //边
    {
        e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
        e[nume++][2]=0;
        e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
        e[nume++][2]=0;
    }
    int headq[maxv];int numq=0;long long  q[maxe][5];
    void inline addq(int x,int y,long long  vals,int flag)    //询问
    {
        q[numq][0]=y;q[numq][1]=headq[x];headq[x]=numq;
        q[numq][2]=-1;q[numq][3]=vals;q[numq++][4]=flag;
        q[numq][0]=x;q[numq][1]=headq[y];headq[y]=numq;
        q[numq][2]=-1;q[numq][3]=vals;q[numq++][4]=flag;
    }
    int fa[maxv];
    int find(int x)
    {
        if(x!=fa[x])
        return fa[x]=find(fa[x]);
        return fa[x];
    }
    int ve[maxv];
    int n,m;
    int vis[maxv];int vis2[maxv];
    long long  val[maxv];
    int ise[maxe];
    void tarjan(int u,int father)             //离线求lca
    {
        for(int j=head[u];j!=-1;j=e[j][1])
        {
            int v=e[j][0];
            if(!vis[v]&&v!=father)
            {
                ve[v]=j;
                ise[j]=1;
                tarjan(v,u);
                fa[v]=u;
            }
        }
        vis[u]=1;
        for(int j=headq[u];j!=-1;j=q[j][1])
        {
            if(vis[q[j][0]])
            {
               q[j^1][2]=q[j][2]=find(q[j][0]);
            }
        }
    }
    void dfs(int u)              //求出全部点边情况
    {
         for(int j=head[u];j!=-1;j=e[j][1])
        {
            int v=e[j][0];
            if(!vis2[v])
            {
                vis2[v]=1;
                dfs(v);
                val[u]+=val[v];
                e[ve[u]][2]+=e[ve[v]][2];
            }
        }
    }
    int vis_e[maxe];
    long long anster[maxv];
    void init()
    {
           nume=numq=0;
        for(int i=0;i<maxv;i++)
        {
            head[i]=headq[i]=-1;
            fa[i]=i;
            val[i]=vis2[i]=vis[i]=0;
            ve[i]=2*n;
            anster[i]=0;
        }
        for(int i=0;i<maxe;i++)
         {
             ise[i]=0;
             vis_e[i]=0;
         }
    }
    template <class T>                  //输入挂
    inline bool scan(T &ret) {
    	char c; int sgn;
    	if(c=getchar(),c==EOF) return 0;     //EOF
    	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    	sgn=(c=='-')?-1:1;
    	ret=(c=='-')?0:(c-'0');
    	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    	ret*=sgn;
    	return 1;
    }
    /*inline void prints(long long x) {
    	if(x>9) prints(x/10);
    	putchar(x%10+'0');
    }*/
    int main()
    {
        int T;int cnt=1;
        scan(T);
        //scanf("%d",&T);
        while(T--)
        {
            //scanf("%d%d",&n,&m);
            scan(n);scan(m);
            init();
            int  aa,bb,cc;
            for(int i=0;i<n-1;i++)
            {
               // scanf("%d%d",&aa,&bb);
                scan(aa);scan(bb);
                adde(aa,bb);
            }
             int tx;
            for(int i=0;i<m;i++)
            {
    
                getchar();getchar();getchar();//getchar();
                 //scanf("ADD");
                 scan(tx);
                 scan(aa);scan(bb);scan(cc);
               //  scanf("%d%d%d%d",&tx,&aa,&bb,&cc);
                 if(tx==1)
                     addq(aa,bb,cc,1);
                 else
                     addq(aa,bb,cc,0);
            }
            tarjan(n/2+1,-1);
         for(int i=1;i<=n;i++)
            for(int j=headq[i];j!=-1;j=q[j][1])
            {
               if(!vis_e[j])
               {
                vis_e[j]=vis_e[j^1]=1;
                if(q[j][4])
                {
                    val[i]+=q[j][3];
                    val[q[j][0]]+=q[j][3];
                    val[q[j][2]]-=q[j][3]*2;
                    anster[q[j][2]]+=q[j][3];
                }
                else
                {
                    e[ve[i]][2]+=q[j][3];
                    e[ve[q[j][0]]][2]+=q[j][3];
                    e[ve[q[j][2]]][2]-=2*q[j][3];
                }
               }
            }
            vis2[n/2+1]=1;
            dfs(n/2+1);
           printf("Case #%d:
    ",cnt++);
           for(int i=1;i<n;i++)
               printf("%I64d ",val[i]+anster[i]);
            printf("%I64d
    ",val[n]+anster[n]);
           for(int j=0;j<nume;j++)
              if(ise[j])
                {
                     if(j==nume-2||j==nume-1)printf("%I64d",e[j][2]);
                     else printf("%I64d ",e[j][2]);
                }
           puts("");
        }
        return 0;
    }
    


  • 相关阅读:
    vmware图形化安装kali iso镜像文件启动后黑屏问题解决方法
    8818驱动蓝屏报错解决方法
    v3ray提示已经在运行的错误
    逆向工程之安卓逆向- --- p命名法中插入一个新寄存器
    硬件黑客之无线电 --- Proxmark3 RDV4 套件
    硬件黑客之无线电 --- Plunder Bug LAN Tap
    硬件黑客之局域网安全 --- 鲨鱼杰克
    硬件黑客之无线电 --- Proxmark3 RDV4 套件
    硬件黑客之无线电 --- NFC Kill
    硬件黑客之无线电 --- 双频 WiFi RTL8812AU
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6763370.html
Copyright © 2020-2023  润新知