• BZOJ4919 大根堆(动态规划+treap+启发式合并)


      一个显然的dp是设f[i][j]为i子树内权值<=j时的答案,则f[i][j]=Σf[son][j],f[i][a[i]]++,f[i][a[i]+1~n]对其取max。这样是可以线段树合并的,但实在太弱了不太会。

      另一种做法是考虑扩展经典的单调队列优化LIS的做法,维护子树内答案为k时最小的最大值,用平衡树维护,在父亲处启发式合并,然后将父亲处权值插入即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    #define lson tree[k].ch[0]
    #define rson tree[k].ch[1]
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,a[N],b[N],fa[N],p[N],root[N],t,cnt;
    struct data{int to,nxt;
    }edge[N<<1];
    struct data2{int x,p,ch[2],s;
    }tree[N<<5];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void up(int k){tree[k].s=tree[lson].s+tree[rson].s+1;}
    void move(int &k,int p)
    {
        int t=tree[k].ch[p];
        tree[k].ch[p]=tree[t].ch[!p],tree[t].ch[!p]=k,up(k),up(t),k=t;
    }
    void ins(int &k,int x)
    {
        if (k==0) {k=++cnt;tree[k].x=x,tree[k].p=rand(),tree[k].s=1;return;}
        tree[k].s++;
        if (tree[k].x<x) {ins(rson,x);if (tree[rson].p>tree[k].p) move(k,1);}
        else {ins(lson,x);if (tree[lson].p>tree[k].p) move(k,0);}
    }
    void del(int &k,int x)
    {
        if (tree[k].x==x)
        {
            if (lson==0||rson==0) {k=lson|rson;return;}
            if (tree[lson].p>tree[rson].p) move(k,0),del(rson,x);
            else move(k,1),del(lson,x);
        }
        else if (tree[k].x<x) del(rson,x);
        else del(lson,x);
        up(k);
    }
    int qrank(int k,int x)
    {
        if (!k) return 0;
        if (tree[k].x>=x) return qrank(lson,x);
        else return qrank(rson,x)+tree[lson].s+1;
    }
    int find(int k,int x)
    {
        if (tree[lson].s+1==x) return tree[k].x;
        if (tree[lson].s+1>x) return find(lson,x);
        else return find(rson,x-tree[lson].s-1);
    }
    void dfsins(int k,int &x)
    {
        if (!k) return;
        ins(x,tree[k].x);
        dfsins(lson,x),dfsins(rson,x);
    }
    int merge(int x,int y)
    {
        if (tree[x].s<tree[y].s) swap(x,y);
        dfsins(y,x);
        return x;
    }
    void dfs(int k)
    {
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=fa[k])
        {
            dfs(edge[i].to);
            root[k]=merge(root[k],root[edge[i].to]);
        }
        int x=qrank(root[k],a[k]);
        if (x<tree[root[k]].s) del(root[k],find(root[k],x+1));
        ins(root[k],a[k]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4919.in","r",stdin);
        freopen("bzoj4919.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();srand(20020509);
        for (int i=1;i<=n;i++)
        {
            b[i]=a[i]=read(),fa[i]=read();
            addedge(fa[i],i);
        }
        sort(b+1,b+n+1);
        int u=unique(b+1,b+n+1)-b-1;
        for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+u+1,a[i])-b;
        dfs(1);
        cout<<tree[root[1]].s;
        return 0;
    }
  • 相关阅读:
    戴尔服务器状态信息和简单处理
    zabbix3.2通过snmp v2采集Dell服务器iDRAC口信息监控硬件
    戴尔服务器使用omreport(OMSA)查看监控硬件信息
    SVN主从高可用
    Linux下ping命令参数详细解析
    记录脚本运行时间
    Centos6优化系统服务脚本
    git分支管理
    git基本操作
    开源CMDB详细安装使用
  • 原文地址:https://www.cnblogs.com/Gloid/p/10046788.html
Copyright © 2020-2023  润新知