首页 > 代码库 > hdu 5044 树区间操作最后输出/ lca+dfs

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:\n",cnt++);
       for(int i=1;i<n;i++)
           printf("%I64d ",val[i]+anster[i]);
        printf("%I64d\n",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;
}


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