zoukankan      html  css  js  c++  java
  • BZOJ 2225: [Spoj 2371]Another Longest Increasing (CDQ分治+dp)

    题面

    Description
    给定N个数对(xi, yi),求最长上升子序列的长度。上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj。

    Input
    Output
    Sample Input
    8

    1 3

    3 2

    1 1

    4 5

    6 3

    9 9

    8 7

    7 6
    Sample Output
    3
    HINT

    数据范围100000

    解题思路

      CDQ分治。其实跟模板题的思路差不多,就是用树状数组维护(dp)最大值。注意一下更新的顺序,就是要从左边往右边更新,所以应该先向左分治,再处理,再向右分治。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
     
    using namespace std;
    const int MAXN = 100005;
     
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
     
    int n,dp[MAXN],f[MAXN],cpy[MAXN],u,ans;
    struct Data{
        int id,x,y;
        friend bool operator<(const Data A,const Data B){
        	return A.x<B.x;
    	}
    }data[MAXN],tmp[MAXN];
     
    inline void add(int x,int k){
        for(;x<=u;x+=x&-x) f[x]=max(f[x],k); 
    }
     
    inline int query(int x){
        int ret=0;
        for(;x;x-=x&-x) ret=max(ret,f[x]);
        return ret;
    }
     
    inline void clear(int x){
        for(;x<=u;x+=x&-x) f[x]=-1;
    }
    
    inline bool cmp(Data A,Data B){
    	return A.id<B.id;
    }
     
    void cdq(int l,int r){
        if(l==r) return ;int mid=(l+r)>>1;cdq(l,mid);
        int L=l,R=mid+1,o=l;
    	sort(data+mid+1,data+r+1);
        while(L<=mid && R<=r){
            if(data[L].x<data[R].x) add(data[L].y,dp[data[L].id]),L++;
            else dp[data[R].id]=max(dp[data[R].id],query(data[R].y-1)+1),R++;
        } 
        while(R<=r) {dp[data[R].id]=max(dp[data[R].id],query(data[R].y-1)+1);R++;}
        for(int i=l;i<=mid;i++) clear(data[i].y);sort(data+mid+1,data+r+1,cmp);
    	cdq(mid+1,r);L=l;R=mid+1;
        while(L<=mid && R<=r) {
        	if(data[L].x<data[R].x) tmp[o++]=data[L++];
        	else tmp[o++]=data[R++];
    	}
    	while(L<=mid) tmp[o++]=data[L++];
    	while(R<=r) tmp[o++]=data[R++]; 
        for(int i=l;i<=r;i++) data[i]=tmp[i];
    }
     
    int main(){
        memset(f,-1,sizeof(f));n=rd();
        for(int i=1;i<=n;i++) data[i].x=rd(),data[i].y=cpy[i]=rd(),data[i].id=i,dp[i]=1; 
        sort(cpy+1,cpy+1+n);u=unique(cpy+1,cpy+1+n)-cpy-1;
        for(int i=1;i<=n;i++) data[i].y=lower_bound(cpy+1,cpy+1+u,data[i].y)-cpy;cdq(1,n);
    	for(int i=1;i<=n;i++)
    		ans=max(ans,dp[i]);
    	printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    有关vue项目中可以用到的动画库(过渡效果等)
    有关vue中v-if和v-show的区别
    有关vue中的计算属性与方法、计算属性与监听属性的区别
    有关vue中导航守卫的理解
    有关vue中路由的理解
    console 对象与控制台
    有关JavaScript中字符串处理Base64 转码的介绍
    Promise请求在请求消息头添加token值 a-upload访问接口时添加请求消息头信息
    【Python-2.7】换行符和制表符
    【Python-2.7】大小写转换函数
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10024313.html
Copyright © 2011-2022 走看看