• 洛谷 4115 Qtree4——链分治


    题目:https://www.luogu.org/problemnew/show/P4115

    论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb602.html

    重链剖分,分别用线段树维护每条重链。线段树叶子的信息是该点轻孩子的信息;线段树区间的信息是考虑重链的一个区间以及附带的轻孩子们的信息。

    修改一个点,改它所在的重链的信息。祖先的每条重链都有一个点的 “轻孩子信息” 改变了,改一下那个位置的值,更新它的线段树,再用该重链的信息作为轻孩子更新更上面的重链。

    本题每个点要维护的是 “向下以白点为端点的最长链” 和 “向下以白点为端点的次长链” 。用可删堆维护。

    线段树区间维护 “从左边开始、以白点结束的最长链” 、 “从右边开始、以白点结束的最长链” 、 “中间一条两端点都是白点的最长链” 。前两个信息是为了更新第三个信息。

    每条重链的答案放进全局可删堆中。

    注意求 “次长链” 的时候,自己是先把堆顶拿出来,再看剩下的堆的堆顶。要注意再看之前先用删除堆更新一下!

    预处理的时候,自己想一个一个插入。在 pshp 的时候要用到兄弟的 fl , fr , pr , sc 等信息。所以得先把线段树整个建出来,不能有些孩子是空的就开始 pshp 。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ls Ls[cr]
    #define rs Rs[cr]
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int Mx(int a,int b){return a>b?a:b;}
    int Mn(int a,int b){return a<b?a:b;}
    const int N=1e5+5,M=2e5+5,INF=1e9,Lm=-1e8;
    int n,hd[N],xnt,to[M],nxt[M],w[M]; bool col[N];
    int siz[N],son[M],dep[N],fa[N],fw[N],top[N];
    int dis[N],dp2[N],lm[N],tot,rt[N],Ls[M],Rs[M];
    int dy[N],fl[M],fr[M],mx[M],pr[M],sc[M];
    priority_queue<int> q[N],dq[N],ans,dans;
    int Dis(int x,int y){return dp2[y]-dp2[x];}
    void frs(int x)
    {
      while(dq[x].size()&&q[x].top()==dq[x].top())
        q[x].pop(), dq[x].pop();
    }
    void pshp(int cr)
    {
      pr[cr]=pr[ls]; sc[cr]=sc[rs];
      fl[cr]=Mx(fl[ls],Dis(pr[cr],pr[rs])+fl[rs]);
      fr[cr]=Mx(fr[rs],Dis(sc[ls],sc[cr])+fr[ls]);
      mx[cr]=Mx(Dis(sc[ls],pr[rs])+fr[ls]+fl[rs],Mx(mx[ls],mx[rs]));
    }
    void build(int l,int r,int &cr)
    {
      cr=++tot;fl[cr]=fr[cr]=mx[cr]=-INF;
      pr[cr]=dy[l]; sc[cr]=dy[r];
      if(l==r)return; int mid=l+r>>1;
      build(l,mid,ls); build(mid+1,r,rs);
    }
    void updt(int l,int r,int cr,int p,int k)
    {
      if(l==r)
        {
          fl[cr]=fr[cr]=dis[k]; pr[cr]=sc[cr]=k;
          if(!q[k].size()){ mx[cr]=-INF; return;}
          q[k].pop(); frs(k);//////
          int d2=-INF;
          if(q[k].size())d2=q[k].top();
          if(!col[k])mx[cr]=Mx(dis[k]+d2,Mx(dis[k],d2));
          //col[k] not col[cr]!!
          else mx[cr]=dis[k]+d2;
          q[k].push(dis[k]);
          return;
        }
      int mid=l+r>>1;
      if(p<=mid)updt(l,mid,ls,p,k); else updt(mid+1,r,rs,p,k);
      pshp(cr);
    }
    void add(int x,int y,int z)
    {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;}
    void dfs(int cr,int f)
    {
      dep[cr]=dep[f]+1; dp2[cr]=dp2[f]+fw[cr];
      fa[cr]=f; siz[cr]=1;
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=f)
          {
        fw[v]=w[i]; dfs(v,cr); siz[cr]+=siz[v];
        if(siz[v]>siz[son[cr]])son[cr]=v;
          }
    }
    int Ps(int cr){return dep[cr]-dep[top[cr]]+1;}
    void dfsx(int cr,int f)
    {
      if(son[cr])top[son[cr]]=top[cr],dfsx(son[cr],cr);
      for(int i=hd[cr],v;i;i=nxt[i])
        if((v=to[i])!=f&&v!=son[cr])
          {
        top[v]=v;dfsx(v,cr);
        if(fl[rt[v]]>Lm)q[cr].push(fl[rt[v]]+w[i]);
          }
      if(!col[cr])q[cr].push(0);
      if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;
      int p=Ps(cr),tp=top[cr];
      if(p>lm[tp])
        {
          lm[tp]=p;
          for(int i=p,k=cr;i;i--,k=fa[k])dy[i]=k;
          build(1,p,rt[tp]);
        }
      updt(1,lm[tp],rt[tp],p,cr);
      if(tp==cr)ans.push(mx[rt[cr]]);
    }
    void chg(int cr)
    {
      col[cr]=!col[cr];
      if(!col[cr])q[cr].push(0); else dq[cr].push(0);
      int x=top[cr]; frs(cr);
      if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;
      dans.push(mx[rt[x]]);
      if(fa[x])dq[fa[x]].push(fl[rt[x]]+fw[x]);
      updt(1,lm[x],rt[x],Ps(cr),cr);
      ans.push(mx[rt[x]]);
      if(fa[x])q[fa[x]].push(fl[rt[x]]+fw[x]);
      while(fa[x])
        {
          cr=fa[x]; x=top[cr]; frs(cr);
          if(q[cr].size())dis[cr]=q[cr].top(); else dis[cr]=-INF;
          dans.push(mx[rt[x]]);
          if(fa[x])dq[fa[x]].push(fl[rt[x]]+fw[x]);
          updt(1,lm[x],rt[x],Ps(cr),cr);
          ans.push(mx[rt[x]]);
          if(fa[x])q[fa[x]].push(fl[rt[x]]+fw[x]);
        }
    }
    int main()
    {
      n=rdn();
      for(int i=1,u,v,z;i<n;i++)
        {
          u=rdn();v=rdn();z=rdn();
          add(u,v,z);add(v,u,z);
        }
      dfs(1,0); top[1]=1; dfsx(1,0);
      int Q=rdn(); char ch;int x;
      while(Q--)
        {
          cin>>ch;
          if(ch=='A')
        {
          while(dans.size()&&ans.top()==dans.top())
            ans.pop(),dans.pop();
          if(ans.top()<Lm)puts("They have disappeared.");
          else printf("%d
    ",ans.top());
        }
          else
        { x=rdn(); chg(x);}
        }
      return 0;
    }
  • 相关阅读:
    如何使用Remoting实现双工(转自Artech)
    解决自定义代码启动Approver Sharepoint 2010 Workflow,出现Failed on Start
    设计模式学习(目录)
    C#面向对象分析
    使用Sharepoint 2010 Client Object Model 通过SSL验证
    .NET 4.0 Location : 查看传感器状态变化
    OLAP和OLTP的 概念和区别
    组织结构及权限模型设计
    维度关系
    PHP正则替换中文让中文无处可躲
  • 原文地址:https://www.cnblogs.com/Narh/p/10776851.html
Copyright © 2020-2023  润新知