【bzoj3589】动态树 树链剖分+树链的并

题解:

树链剖分是显然的

问题在于求树链的并

比较简单的方法是

用线段树打标记覆盖,查询标记区间大小

Qlog^2n

代码:

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define rint register int
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
const int N=3e5;
const int N1=N*4;
const int INF=1e9;
int n,l,cnt,dfn[N],size[N],fa[N],top[N],son[N],head[N],dep[N];
struct re{
  int a,b;
}a[N*2];
void arr(int x,int y)
{
  a[++l].a=head[x];
  a[l].b=y;
  head[x]=l;
}
void dfs(int x,int y)
{
  fa[x]=y; size[x]=1;
  int u=head[x];
  dep[x]=dep[y]+1;
  while (u)
  {
    int v=a[u].b;
    if (v!=y)
    { 
      dfs(v,x);
      if (size[v]>size[son[x]]) son[x]=v;
      size[x]+=size[v];
    }
    u=a[u].a;
  }
}
void dfs2(int x,int y)
{
  dfn[x]=++cnt; top[x]=y; 
  if (!son[x]) return;
  dfs2(son[x],y);
  int u=head[x];
  while (u)
  {
    int v=a[u].b;
    if (v!=fa[x]&&v!=son[x]) dfs2(v,v);
    u=a[u].a;
  }
}
struct sgt{

  int sum[N1],sum1[N1],lazy[N1],lazy1[N1];
  #define mid ((h+t)/2)
  IL void clear()
  {
    lazy1[1]=-1; sum1[1]=0;
  }
  IL int query()
  {
    return sum1[1];
  }
  IL void down(int x,int h,int t)
  {
    if (lazy[x])
    {
      sum[x*2]+=(mid-h+1)*lazy[x];
      sum[x*2+1]+=(t-mid)*lazy[x];
      lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x];
      lazy[x]=0;
    }
    if (lazy1[x])
    {
      lazy1[x*2]=lazy1[x*2+1]=lazy1[x];
      if (lazy1[x]==1) sum1[x*2]=sum[x*2],sum1[x*2+1]=sum[x*2+1];
      else sum1[x*2]=sum1[x*2+1]=0; 
      lazy1[x]=0;
    }
  }
  IL void updata(int x)
  {
    sum[x]=sum[x*2]+sum[x*2+1];
    sum1[x]=sum1[x*2]+sum1[x*2+1]; 
  }
  void change(int x,int h,int t,int h1,int t1,int k)
  {
    if (h1<=h&&t<=t1)
    {
      lazy[x]+=k; sum[x]+=(t-h+1)*k; return;
    }
    down(x,h,t);
    if (h1<=mid) change(x*2,h,mid,h1,t1,k);
    if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k);
    updata(x);
  }
  void push(int x,int h,int t,int h1,int t1)
  {
    if (h1<=h&&t<=t1)
    {
      lazy1[x]=1; sum1[x]=sum[x]; return;
    }
    down(x,h,t);
    if (h1<=mid) push(x*2,h,mid,h1,t1);
    if (mid<t1) push(x*2+1,mid+1,t,h1,t1);
    updata(x);
  }
}S;
void change(int x,int y)
{
  int kk=dfn[x];
  S.change(1,1,n,kk,kk+size[x]-1,y);
}
void query(int x,int y)
{
  int f1=top[x],f2=top[y];
  while (top[x]!=top[y])
  {
    if (dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
    S.push(1,1,n,dfn[f1],dfn[x]);
    x=fa[f1]; f1=top[x]; 
  }
  if (dep[x]<dep[y]) swap(x,y);
  S.push(1,1,n,dfn[y],dfn[x]);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>n;
  rep(i,1,n-1)
  {
    int x,y; cin>>x>>y;
    arr(x,y); arr(y,x);
  }
  dfs(1,0);
  dfs2(1,1);
  int m;
  cin>>m;
  rep(i,1,m)
  {
    int kk,x,y,p;
    cin>>kk;
    if (!kk)
    {
      cin>>x>>y;
      change(x,y);
    } else
    {
      cin>>p;
      rep(j,1,p)
      {
        cin>>x>>y;
        query(x,y);
      }
      int ans=S.query();
      if (ans<0) ans+=1<<31;
      cout<<ans<<endl;
      S.clear();
    }
  }
  return 0;
}

 

posted @ 2018-07-24 10:51  尹吴潇  阅读(213)  评论(0编辑  收藏  举报