[HEOI2016/TJOI2016]序列(树套树)

暴力dp

j<i,max[j]<a[i],min[i]>a[j]dp[i]=dp[j]+1 j < i , m a x [ j ] < a [ i ] , m i n [ i ] > a [ j ] d p [ i ] = d p [ j ] + 1

for(int j=1; j<i; ++j)
    if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次 
        dp[i]=max{dp[j]+1};
for(int j=1; j<i; ++j)    if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次         dp[i]=max{dp[j]+1};

所以把dp值当权值,转换为二维的点,树套树就完了

#include<cstdio>
#include<iostream>
using namespace std;
const int M=401000; 
int n,m,mi[10*M],ma[10*M],a[10*M],cnt,root[10*M],ans,N;
struct xd_tree{
    int maxn,ls,rs;
}t[40*M];
void modify(int &o,int l,int r,int id,int d){
    if(!o) o=++cnt;
    t[o].maxn=max(d,t[o].maxn);
    if(l>=r)    return ;
    int mid=(l+r)>>1;
    if(id<=mid)modify(t[o].ls,l,mid,id,d);
    else modify(t[o].rs,mid+1,r,id,d);
}
int query(int o,int l,int r,int id){
    if(l==r)   return t[o].maxn;
    int mid=(l+r)>>1;
    if(id<=mid)  return query(t[o].ls,l,mid,id);
    else   return max(t[t[o].ls].maxn,query(t[o].rs,mid+1,r,id));   
}
void add(int x,int pos,int val){for(x;x<=N;x+=x&-x) modify(root[x],1,N,pos,val);}
int ask(int x,int pos){int ans=0;for(x;x;x-=x&-x) ans=max(query(root[x],1,N,pos),ans); return ans;}
int main(){
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++) scanf("%d",&a[i]),mi[i]=a[i],ma[i]=a[i];
    for(int i=1,x,y;i<=m;i++){scanf("%d%d",&x,&y);
        mi[x]=min(y,mi[x]);ma[x]=max(ma[x],y);N=max(N,ma[x]);
    }
    for(int i=1;i<=n;i++){
        int now=ask(mi[i],a[i])+1;
        add(a[i],ma[i],now);
        ans=max(now,ans);
    }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值