二维LIS(CDQ分治)

题目描述

给定一个长度为N的序列S,S的每个元素pi是一个二元组(xi,yi),定义pi<pj当且仅当xi<xj并且yi<yj,求S的最长上升子序列长度

输入格式

第一行一个N,表示一共有N个元素

接下来有N行,每行包含两个正整数xi,yi

输出格式

输出一行一个整数,代表序列S的最长上升子序列的长度

 

一道很好的模板题,比较入门吧

CDQ分治+线段树/树状数组维护最大值就好了

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 struct nasm{
 6     int x,y,z;
 7 }a[100000];
 8 int f[1000000];
 9 int tr[1000000];
10 int tmp[100000];
11 int n;
12 bool cmp(nasm g,nasm u)
13 {
14     return g.y<u.y;
15 }
16 bool cmq(nasm g,nasm u)
17 {
18     return g.x<u.x;
19 }
20 void updt(int pi,int v,int l,int r,int spc)
21 {
22     if(l==r)
23     {
24         tr[spc]=v==0?v:max(v,tr[spc]);
25         return ;
26     }
27     int m=(l+r)>>1;
28     if(pi<=m)
29         updt(pi,v,l,m,spc<<1);
30     else    
31         updt(pi,v,m+1,r,spc<<1|1);
32     tr[spc]=max(tr[spc<<1],tr[spc<<1|1]);
33 }
34 int ask(int ll,int rr,int l,int r,int spc)
35 {
36     if(ll>rr)return 0;
37     if(l>=ll&&r<=rr)return tr[spc];
38     int m=(l+r)>>1;
39     if(m>=rr)return ask(ll,rr,l,m,spc<<1);
40     if(m<ll)return ask(ll,rr,m+1,r,spc<<1|1);
41     return max(ask(ll,rr,l,m,spc<<1),ask(ll,rr,m+1,r,spc<<1|1));
42 }
43 void wrk(int l,int r)
44 {
45     int mid=(l+r)>>1;
46     sort(a+l,a+mid+1,cmp);
47     sort(a+mid+1,a+r+1,cmp);
48     for(int i=l,j=mid+1;j<=r;j++)
49     {
50         for(;a[i].y<a[j].y&&i<=mid;i++)
51             updt(a[i].z,f[a[i].x],1,n,1);
52         f[a[j].x]=max(f[a[j].x],ask(1,a[j].z-1,1,n,1)+1);
53     }
54     for(int i=l;i<=mid;i++)updt(a[i].z,0,1,n,1);
55     sort(a+mid+1,a+r+1,cmq);
56 }
57 void cdq(int l,int r)
58 {
59     if(l==r)
60         return ;
61     int mid=(l+r)>>1;
62     cdq(l,mid);
63     wrk(l,r);
64     cdq(mid+1,r);
65     
66 }
67 int erf(int l,int r,int aim)
68 {
69     if(l==r)return l;
70     int m=(l+r)>>1;
71     if(aim<=tmp[m])
72         return erf(l,m,aim);
73     return erf(m+1,r,aim);
74 }
75 int main()
76 {
77     scanf("%d",&n);
78     for(int i=1;i<=n;i++)
79     {
80         scanf("%d%d",&a[i].y,&a[i].z);
81         f[i]=1;
82         a[i].x=i;
83         tmp[i]=a[i].z;
84     }
85     sort(tmp+1,tmp+n+1);
86     for(int i=1;i<=n;i++)
87         a[i].z=erf(1,n,a[i].z);
88     cdq(1,n);
89     int ans=0;
90     for(int i=1;i<=n;i++)
91         ans=max(ans,f[i]);
92     printf("%d\n",ans);
93     return 0;
94 }
二维LIS

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/9404518.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,有几种方式可以实现二维数组。其中两种常见方法是使用列表(list)和使用NumPy库中的数组(ndarray)。 使用列表创建一个二维列表可以通过以下方式实现: ``` lis = [[] for i in range(5)] for i in range(5): lis.append([]) ``` 这样就创建了一个空的二维列表lis。 另一种方法是使用NumPy库中的数组,可以通过以下方式实现: ``` import numpy as np # 创建一维数组 nd_one = np.array([1, 2, 3]) # 创建二维数组 nd_two = np.array([[1, 2, 3], [4, 5, 6]]) print(nd_one) print(nd_two) print('nd_one.shape =', nd_one.shape) print('nd_two.shape =', nd_two.shape) ``` 这样就创建了一个包含一维和二维数组的NumPy数组nd_one和nd_two。输出结果中的shape属性可以用来获取数组的维度信息。 请注意,使用NumPy数组相对于列表的优势在于NumPy提供了更多的功能和数学运算的支持,特别是对于大型数据集的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python如何创建二维数组](https://blog.csdn.net/fan13938409755/article/details/121889926)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Python 创建二维数组](https://blog.csdn.net/flyingluohaipeng/article/details/129828525)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值