zoukankan      html  css  js  c++  java
  • BZOJ 5469: [FJOI2018]领导集团问题 dp+线段树合并

    在 dp 问题中,如果发现可以用后缀最大值来进行转移的话可以考虑去查分这个后缀最大值. 

    这样的话可以用差分的方式来方便地进行维护 ~ 

    #include <bits/stdc++.h> 
    #define N 200007  
    #define ll long long     
    #define lson t[x].ls 
    #define rson t[x].rs                                          
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std;          
    const int MM=1e7+5e6+20;  
    int edges,tot,n;   
    int hd[N],to[N<<1],nex[N<<1],rt[N],A[N],val[N];   
    struct node 
    {
        int ls,rs,sum;   
    }t[MM];      
    inline int newnode() { return ++tot; }  
    inline void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  
    }                   
    void update(int &x,int l,int r,int p,int v) 
    {
        if(!x)  x=newnode(); 
        t[x].sum+=v;          
        if(l==r)    return ;    
        int mid=(l+r)>>1;      
        if(p<=mid)    update(lson,l,mid,p,v); 
        else update(rson,mid+1,r,p,v);     
    }    
    int merge(int x,int y) 
    { 
        if(!x||!y)    return x+y;  
        int now=newnode(); 
        t[now].sum=t[x].sum+t[y].sum;        
        t[now].ls=merge(t[x].ls,t[y].ls);   
        t[now].rs=merge(t[x].rs,t[y].rs);    
        return now;  
    }   
    int find(int x,int l,int r,int p) 
    {
        if(!x)   return 0;   
        if(l==r)   return t[x].sum?l:0;   
        int mid=(l+r)>>1;     
        if(p<=mid) 
        {
            return find(lson,l,mid,p);   
        } 
        else 
        { 
            int pp=find(rson,mid+1,r,p);   
            if(!pp)    return find(lson,l,mid,p); 
            else return pp;     
        }
    }
    void dfs(int u,int ff) 
    {   
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i];     
            dfs(v,u);                 
            rt[u]=merge(rt[u],rt[v]);  
        }    
        update(rt[u],0,n,val[u],1);   
        int pos=find(rt[u],0,n,val[u]-1);        
        if(pos)   update(rt[u],0,n,pos,-1);                    
    }
    int main() 
    { 
        // setIO("input");   
        int i,j; 
        scanf("%d",&n);             
        for(i=1;i<=n;++i)     scanf("%d",&val[i]), A[i]=val[i];               
        sort(A+1,A+1+n);     
        for(i=1;i<=n;++i)     val[i]=lower_bound(A+1,A+1+n,val[i])-A;
        for(i=2;i<=n;++i) 
        {
            int ff;              
            scanf("%d",&ff);    
            add(ff,i);  
        }
        dfs(1,0);           
        printf("%d
    ",t[rt[1]].sum);    
        return 0; 
    }        
    

      

  • 相关阅读:
    oracle字符集查看修改
    oracle查看所有表及字段
    oracle重新启动步骤
    oracle job 定时执行 存储过程
    oracle导入导出exp,imp
    oracle创建表空间
    Oracle Dataguard HA (主备,灾备)方案部署调试
    Moving Tables-贪心
    Windows下Android开发环境配置
    在单进程单线程或单进程多线程下实现log4cplus写日志并按大小切割
  • 原文地址:https://www.cnblogs.com/guangheli/p/11971416.html
Copyright © 2011-2022 走看看