• 【BZOJ4919】[Lydsy六月月赛]大根堆


    题解:

    我觉得数据结构写成结构体还是有必要的

    因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错

     另外初始化用segmenttree(){ }

    首先裸的dp很好想

    f[i][j]表示在i点,最大值<=j的点数最大值

    看了别人的题解知道了可以用线段树合并来优化这个东西。。

    我们考虑对于每个点,首先我们要合并它的子树

    其实就是对于相同位置的点相加即可

    然后考虑当前节点,我们应用f[v[x]-1]+1去更新v[x]-n之间的值(也就是取max操作)

    不然是没法down的

    1.当x,y其中有一个左二子没有的时候

    就需要给它加一个sum标记

    原因是,由于他没有左二子了,说明它对应的左二子的lazy值都是这个

    所以要变成sum标记,对每一个子节点都加上这个

    2.down的时候也要用lazy[fa]更新lazy[x] 原因是有sum[x]的存在

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6;
    const int INF=1e9;
    #define IL inline
    #define rint register int
    int n,m,fa[N],vv[N],head[N],l;
    struct re{
      int a,b;
    }a[N],v[N];
    IL int max(int x,int y)
    {
      int z;
      x>y?z=x:z=y;
      return(z);
    }
    IL int min(int x,int y)
    {
      int z;
      x<y?z=x:z=y;
      return(z);
    }
    void arr(int x,int y)
    {
      a[++l].a=head[x];
      a[l].b=y;
      head[x]=l;
    }
    struct segmenttree
    {
      int cnt,rt[N],sum[N*20],ls[N*20],rs[N*20],lz[N*20];
      #define mid ((h+t)>>1)
      segmenttree(){cnt=0;}
      IL void down(int x)
      {
        if (ls[x]) lz[ls[x]]=max(sum[x]+lz[ls[x]],lz[x]),sum[ls[x]]+=sum[x];
        if (rs[x]) lz[rs[x]]=max(sum[x]+lz[rs[x]],lz[x]),sum[rs[x]]+=sum[x];
        sum[x]=0;
      }
      int merge(int x,int y)
      {
        if (!x||!y) return x^y;
        down(x); down(y);
        if (!ls[x])
          ls[x]=ls[y],lz[ls[x]]+=lz[x],sum[ls[x]]+=lz[x];
        else if (!ls[y])
          lz[ls[x]]+=lz[y],sum[ls[x]]+=lz[y];
        else ls[x]=merge(ls[x],ls[y]);
        if (!rs[x])
          rs[x]=rs[y],lz[rs[x]]+=lz[x],sum[rs[x]]+=lz[x];
        else if (!rs[y])
          lz[rs[x]]+=lz[y],sum[rs[x]]+=lz[y];
        else rs[x]=merge(rs[x],rs[y]);
        lz[x]+=lz[y];
        return x;
      }
      int query(int x,int h,int t,int pos)
      {
        if (x==0) return 0;
        if (h==t) return lz[x];
        down(x);
        if (pos<=mid) return max(lz[x],query(ls[x],h,mid,pos));
        else return max(lz[x],query(rs[x],mid+1,t,pos));
      }
      void change(int &x,int h,int t,int h1,int t1,int k)
      {
        if (!x) x=++cnt;
        if (h1<=h&&t<=t1)
        { 
          lz[x]=max(lz[x],k);
          return;
        }
        down(x);
        if (h1<=mid) change(ls[x],h,mid,h1,t1,k);
        if (mid<t1) change(rs[x],mid+1,t,h1,t1,k);
      }
    }se1;
    void dfs(int x,int fa)
    {
      int u=head[x];
      while (u)
      {
        int v=a[u].b;
        dfs(v,x);
        se1.rt[x]=se1.merge(se1.rt[x],se1.rt[v]);
        u=a[u].a;
      }
      se1.change(se1.rt[x],1,n,vv[x],n,se1.query(se1.rt[x],1,n,vv[x]-1)+1);
    }
    bool cmp(re x,re y)
    {
      return(x.a<y.a);
    }
    int main()
    {
     // freopen("1.in","r",stdin);
      //freopen("1.out","w",stdout);
      cin>>n;
      for (int i=1;i<=n;i++)
      {
        cin>>v[i].a>>fa[i];
        v[i].b=i;
        if (fa[i]) arr(fa[i],i);
      }
      sort(v+1,v+n+1,cmp);
      v[0].a=INF;
      int cnt=0;
      for (int i=1;i<=n;i++)
      {
        if (v[i].a!=v[i-1].a) cnt++;
        vv[v[i].b]=cnt;
      }
      dfs(1,0);
      int ans2=0;
      for(int i=1;i<=n;i++)
          ans2=max(ans2,se1.query(se1.rt[1],1,n,i));
      cout<<ans2;
      return 0;
    }
  • 相关阅读:
    多种方式实现 Future 回调返回结果
    Google Guava ListeningExecutorService
    MySQL数据库的核心MVCC详解
    共收录 Twitter 的 14 款开源软件,第 1 页
    共收录 微软 的 62 款开源软件,第 1 页
    共收录 腾讯 的 48 款开源软件,第 1 页
    共收录 Netflix 的 22 款开源软件,第 1 页
    什么是yml文件
    共收录 NASA 的 26 款开源软件,第 1 页
    共收录 Github 的 5 款开源软件,第 1 页
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9060320.html
Copyright © 2020-2023  润新知