zoukankan      html  css  js  c++  java
  • 【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”

    裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define N 100001
    #define BN 320
    #define INF 2147483647
    int fa[N],dep[N],siz[N],son[N],Num[N],tot,top[N],a[N],bw[N],n,A[N],B[N],bs[N];
    int en,first[N],next[N<<1],v[N<<1],sz,NOT;
    void AddEdge(const int &U,const int &V)
    {
    	v[++en]=V;
    	next[en]=first[U];
    	first[U]=en;
    }
    void dfs(int U,int Fa,int d)
    {
        fa[U]=Fa;
        dep[U]=d;
        siz[U]=1;
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U])
            {
              dfs(v[i],U,d+1);
              siz[U]+=siz[v[i]];
              if(siz[v[i]]>siz[son[U]])
                son[U]=v[i];
            }
    }
    void dfs2(int U)
    {
    	if(son[U])
    	  {
    	  	top[son[U]]=top[U];
    	  	Num[son[U]]=++tot;
    	  	dfs2(son[U]);
    	  }
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U]&&v[i]!=son[U])
            {
              top[v[i]]=v[i];
              Num[v[i]]=++tot;
              dfs2(v[i]);
            }
    }
    int SIZ[N],TOP[N];
    void dfs3(int U)
    {
        for(int i=first[U];i;i=next[i])
          if(v[i]!=fa[U])
            {
              if(SIZ[TOP[U]]<sz)
                {
                  TOP[v[i]]=TOP[U];
                  ++SIZ[TOP[U]];
                }
              dfs3(v[i]);
            }
    }
    int lca(int U,int V)
    {
        while(U!=V)
          {
            if(TOP[U]!=TOP[V])
              {
                if(dep[TOP[U]]<dep[TOP[V]])
    			  swap(U,V);
                U=fa[TOP[U]];
              }
            else
              {
                if(dep[U]<dep[V])
    			  swap(U,V);
                U=fa[U];
              }
          }
        return U;
    }
    int sum=1,num[N],l[BN],r[BN],maxv[BN],cov[BN],add[BN];
    void makeblock()
    {
    	for(;sum*sz<n;++sum)
    	  {
    	  	l[sum]=r[sum-1]+1;
    	  	r[sum]=sum*sz;
    	  	maxv[sum]=-INF;
    	  	cov[sum]=INF;
    	  	for(int i=l[sum];i<=r[sum];++i)
    	  	  {
    	  	  	num[i]=sum;
    	  	  	maxv[sum]=max(maxv[sum],a[i]);
    	  	  }
    	  }
    	l[sum]=r[sum-1]+1;
    	r[sum]=n;
    	maxv[sum]=-INF;
    	cov[sum]=INF;
    	for(int i=l[sum];i<=r[sum];++i)
    	  {
    	  	num[i]=sum;
    	  	maxv[sum]=max(maxv[sum],a[i]);
    	  }
    }
    void work_cov(const int &x,const int &y,const int &v)
    {
    	for(int i=x;i<=y;++i)
    	  a[i]=v;
    }
    void work_add(const int &x,const int &y,const int &v)
    {
    	for(int i=x;i<=y;++i)
    	  a[i]+=v;
    }
    void pushdown(const int &bl)
    {
    	if(cov[bl]!=INF)
    	  {
    	  	work_cov(l[bl],r[bl],cov[bl]);
    	  	cov[bl]=INF;
    	  }
    	if(add[bl])
    	  {
    	  	work_add(l[bl],r[bl],add[bl]);
    	  	add[bl]=0;
    	  }
    }
    void calc(const int &bl)
    {
    	maxv[bl]=-INF;
    	for(int i=l[bl];i<=r[bl];++i)
    	  maxv[bl]=max(maxv[bl],a[i]);
    }
    void Update0(const int &x,const int &y)
    {
    	int pl=Num[bs[x]];
    	pushdown(num[pl]);
    	a[pl]=y;
    	calc(num[pl]);
    }
    void Cov(const int &x,const int &y,const int &v)
    {
    	pushdown(num[x]);
    	pushdown(num[y]);
    	if(num[x]==num[y])
    	  {
    	  	work_cov(x,y,v);
    	  	calc(num[x]);
    	  }
    	else
    	  {
    	  	work_cov(x,r[num[x]],v);
    	  	calc(num[x]);
    	  	work_cov(l[num[y]],y,v);
    	  	calc(num[y]);
    	  	for(int i=num[x]+1;i<num[y];++i)
    	  	  {
    	  	  	add[i]=0;
    	  	  	cov[i]=maxv[i]=v;
    	  	  }
    	  }
    }
    void Add(const int &x,const int &y,const int &v)
    {
    	pushdown(num[x]);
    	pushdown(num[y]);
    	if(num[x]==num[y])
    	  {
    	  	work_add(x,y,v);
    	  	calc(num[x]);
    	  }
    	else
    	  {
    	  	work_add(x,r[num[x]],v);
    	  	calc(num[x]);
    	  	work_add(l[num[y]],y,v);
    	  	calc(num[y]);
    	  	for(int i=num[x]+1;i<num[y];++i)
    	  	  {
    	  	  	add[i]+=v;
    	  	  	maxv[i]+=v;
    	  	  }
    	  }
    }
    int Query(const int &x,const int &y)
    {
    	int res=-INF;
    	pushdown(num[x]);
    	pushdown(num[y]);
    	if(num[x]==num[y])
    	  for(int i=x;i<=y;++i)
    	  	res=max(res,a[i]);
    	else
    	  {
    	  	for(int i=x;i<=r[num[x]];++i)
    		  res=max(res,a[i]);
    	  	for(int i=l[num[y]];i<=y;++i)
    		  res=max(res,a[i]);
    		for(int i=num[x]+1;i<num[y];++i)
    		  res=max(res,maxv[i]);
    	  }
    	return res;
    }
    void Change_cov(const int &L,const int &R,const int &W)
    {
    	if(L==R&&Num[NOT]==L) return;
    	if(Num[NOT]==L) Cov(L+1,R,W);
    	else if(Num[NOT]==R) Cov(L,R-1,W);
    	else if(Num[NOT]>L&&Num[NOT]<R)
    	  {
    	  	Cov(L,Num[NOT]-1,W);
    	  	Cov(Num[NOT]+1,R,W);
    	  }
    	else Cov(L,R,W);
    }
    void Update_cov(int U,int V,const int &W)
    {
    	int f1=top[U],f2=top[V];
    	while(f1!=f2)
    	  {
    	  	if(dep[f1]<dep[f2])
              {
                swap(U,V);
                swap(f1,f2);
              }
            Change_cov(Num[f1],Num[U],W);
            U=fa[f1];
            f1=top[U];
    	  }
    	if(dep[U]>dep[V])
    	  swap(U,V);
        Change_cov(Num[U],Num[V],W);
    }
    void Change_add(const int &L,const int &R,const int &W)
    {
    	if(L==R&&Num[NOT]==L) return;
    	if(Num[NOT]==L) Add(L+1,R,W);
    	else if(Num[NOT]==R) Add(L,R-1,W);
    	else if(Num[NOT]>L&&Num[NOT]<R)
    	  {
    	  	Add(L,Num[NOT]-1,W);
    	  	Add(Num[NOT]+1,R,W);
    	  }
    	else Add(L,R,W);
    }
    void Update_add(int U,int V,const int &W)
    {
    	int f1=top[U],f2=top[V];
    	while(f1!=f2)
    	  {
    	  	if(dep[f1]<dep[f2])
              {
                swap(U,V);
                swap(f1,f2);
              }
            Change_add(Num[f1],Num[U],W);
            U=fa[f1];
            f1=top[U];
    	  }
    	if(dep[U]>dep[V])
    	  swap(U,V);
        Change_add(Num[U],Num[V],W);
    }
    int Talk(const int &L,const int &R)
    {
    	if(L==R&&Num[NOT]==L) return (-INF);
    	if(Num[NOT]==L) return Query(L+1,R);
    	if(Num[NOT]==R) return Query(L,R-1);
    	if(Num[NOT]>L&&Num[NOT]<R) return max(Query(L,Num[NOT]-1),Query(Num[NOT]+1,R));
    	return Query(L,R);
    }
    int Query_max(int U,int V)
    {
    	int f1=top[U],f2=top[V],res=-INF;
    	while(f1!=f2)
    	  {
    	  	if(dep[f1]<dep[f2])
              {
                swap(U,V);
                swap(f1,f2);
              }
            res=max(res,Talk(Num[f1],Num[U]));
            U=fa[f1];
            f1=top[U];
    	  }
    	if(dep[U]>dep[V])
    	  swap(U,V);
        return max(res,Talk(Num[U],Num[V]));
    }
    //int cnt,LL[N],RR[N];
    //void dfs4(int U)
    //{
    //	LL[U]=++cnt;
    //	for(int i=first[U];i;i=next[i])
    //	  if(v[i]!=fa[U])
    //	    dfs4(v[i]);
    //	RR[U]=cnt;
    //}
    //int Init(const int &x,const int &y)
    //{
    //	if(y>=LL[x]&&y<=RR[x]) return x;
    //	if(x>=LL[y]&&x<=RR[y]) return y;
    //	return lca(x,y);
    //}
    int main()
    {
    //	freopen("bzoj1984.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<n;++i)
    	  {
    	  	scanf("%d%d%d",&A[i],&B[i],&bw[i]);
    	  	AddEdge(A[i],B[i]);
    	  	AddEdge(B[i],A[i]);
    	  }
        top[1]=1;
        Num[1]=++tot;
        dfs(1,0,1);
        dfs2(1);
        sz=sqrt(n); if(!sz) sz=1;
        for(int i=1;i<=n;i++)
    	  {
    	  	SIZ[i]=1;
    		TOP[i]=i;
    	  }
        dfs3(1);
        for(int i=1;i<n;++i)
          {
          	if(fa[A[i]]==B[i])
              bs[i]=A[i];
            else
              bs[i]=B[i];
            a[Num[bs[i]]]=bw[i];
          }
        a[Num[1]]=-INF;
        makeblock();
    //  dfs4(1);
    	char op[7];
    	int x,y,z;
    	while(1)
    	  {
    	  	scanf("%s",op);
    	  	if(op[0]=='S') break;
    	  	scanf("%d%d",&x,&y);
    	  	if(op[0]=='C'&&op[1]=='h') Update0(x,y);
    	  	else if(op[0]=='C'&&op[1]=='o')
    		  {
    		  	NOT=lca(x,y);
    		  	scanf("%d",&z);
    		  	Update_cov(x,y,z);
    		  }
    		else if(op[0]=='A')
    		  {
    		  	NOT=lca(x,y);
    		  	scanf("%d",&z);
    		  	Update_add(x,y,z);
    		  }
    		else
    		  {
    		  	NOT=lca(x,y);
    		    printf("%d
    ",Query_max(x,y));
    		  }
    	  }
    	return 0;
    }
  • 相关阅读:
    《你必须知道的495个C语言问题》读书笔记之第15-20章:浮点数、风格、杂项
    《你必须知道的495个C语言问题》读书笔记之第8-10章:字符串、布尔类型和预处理器
    《你必须知道的495个C语言问题》读书笔记之第4-7章:指针
    《你必须知道的495个C语言问题》读书笔记之第3章:表达式
    《你必须知道的495个C语言问题》读书笔记之第1-2章:声明和初始化
    bzoj4361 isn(树状数组优化dp+容斥)
    bzoj4665 小w的喜糖(dp+容斥)
    P4859 已经没有什么好害怕的了(dp+二项式反演)
    bzoj4710 [Jsoi2011]分特产(容斥)
    bzoj2839 集合计数(容斥)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4321960.html
Copyright © 2011-2022 走看看