• 【SPOJ2371】LIS2


    题目大意:求二维最长上升子序列的长度。

    题解:
    可以看出,这个问题等价于三维偏序问题。
    不过在进行分治的时候要注意,由于 dp 转移是有顺序的,因此只能先处理左半部分,再处理左半部分对右边的贡献,最后处理右半部分。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    
    int n,ans,d[maxn],tot,dp[maxn];
    struct node{int x,y,id;}p[maxn],tmp[maxn];
    int bit[maxn];
    void modify(int pos,int val){
    	for(int i=pos;i<=tot;i+=i&-i)bit[i]=max(bit[i],val);
    }
    int query(int pos){
    	int ret=0;
    	for(int i=pos;i;i-=i&-i)ret=max(ret,bit[i]);
    	return ret;
    }
    void clear(int pos){
    	for(int i=pos;i<=tot;i+=i&-i)bit[i]=0;
    }
    
    void cdq(int l,int r){
    	if(l==r)return;
    	int mid=l+r>>1;
    	cdq(l,mid);
    	sort(p+l,p+mid+1,[](const node &a,const node &b){return a.x<b.x;});
    	sort(p+mid+1,p+r+1,[](const node &a,const node &b){return a.x<b.x;});
    	for(int x=l,y=mid+1;y<=r;y++){
    		while(x<=mid&&p[x].x<p[y].x)modify(p[x].y,dp[p[x].id]),++x;
    		dp[p[y].id]=max(dp[p[y].id],query(p[y].y-1)+1);
    	}
    	for(int i=l;i<=mid;i++)clear(p[i].y);
    	sort(p+mid+1,p+r+1,[](const node &a,const node &b){return a.id<b.id;});
    	cdq(mid+1,r);
    }
    void read_and_parse(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d%d",&p[i].x,&p[i].y);
    		p[i].id=i,d[++tot]=p[i].y;
    	}
    	sort(d+1,d+tot+1);
    	tot=unique(d+1,d+tot+1)-d-1;
    	for(int i=1;i<=n;i++)p[i].y=lower_bound(d+1,d+tot+1,p[i].y)-d;
    }
    void solve(){
    	for(int i=1;i<=n;i++)dp[i]=1;
    	cdq(1,n);
    	for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
    	printf("%d
    ",ans);
    }
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    shell编程—简介(一)
    短信验证码测试项
    测试,不断成长
    初探软件测试心理学
    观察力,细心需要强化
    1=4,2=8,3=24,4=??问题
    IOS空数据页面,网络加载失败以及重新登陆View的封装(不需要继承)
    iOS 快速排序
    iOS支付宝,微信,银联支付集成封装调用(下)
    iOS支付宝,微信,银联支付集成封装(上)
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/11110182.html
Copyright © 2020-2023  润新知