• 【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;
    }
  • 相关阅读:
    FreeModbus TCP
    C#之用户自定义控件
    使用C库制作DLL
    C# Unable to load DLL 'WzCanDll.dll':找不到指定的模块
    C#之改变窗体icon图标、新建类文件、调用dll库
    sim800c GPRS模块的透传模式
    STM32上使用JSON
    STM32之串口IAP更新升级
    Fortran语言的REWIND和BACKSPACE 函数
    Code blocks 编译Fortran(转载)
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9358742.html
Copyright © 2020-2023  润新知