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\n",t[rt[1]].sum);    
    return 0; 
}        

  

posted @ 2019-12-02 16:25  EM-LGH  阅读(162)  评论(0编辑  收藏  举报