二维LIS(CDQ分治)

题目描述

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

输入格式

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

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

输出格式

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

一道很好的模板题

 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

时间: 2024-10-12 12:04:44

二维LIS(CDQ分治)的相关文章

51nod 1376: 最长递增子序列的数量(二维偏序+cdq分治)

1376 最长递增子序列的数量 Time Limit: 1 Sec Memory Limit: 128MB 分值: 160 难度:6级算法题 Description 数组A包含N个整数(可能包含相同的值).设S为A的子序列且S中的元素是递增的,则S为A的递增子序列.如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS).A的LIS可能有很多个.例如A为:{1 3 2 0 4},1 3 4,1 2 4均为A的LIS.给出数组A,求A的LIS有多少个.由于数量很大,输出Mod 1

HDU 1025 Constructing Roads In JGShining&#39;s Kingdom(二维LIS)

Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 23467    Accepted Submission(s): 6710 Problem Description JGShining's kingdom consists of 2n(n is no mo

acd - 1216 - Beautiful People(二维LIS)

题意:一个人有两个属性S, B(1 ≤ Si, Bi ≤ 10^9),当两个人的这两个属性满足 S1 < S2 && B1 < B2 或者 S1 > S2 && B1 > B2 时,这两个人不会讨厌对方.现给出 N 个人(2 ≤ N ≤ 100 000)的属性,求最多能有多少个人,他们之间任意两人都不会讨厌对方. 题目链接:http://acdream.info/problem?pid=1216 -->>容易想到是一个二维的LIS模型..

UVA10285 二维 LIS

题意: 求二维数组最长不下降子序列 解题: 记忆化搜索, d[i][j]为以 (i, j) 为终点的最长不下降序列的长度,然后四个方向 dfs ~ #include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 110; const int INF = 0x3f3f3f3f; char nm[maxn]; int a[maxn][maxn], d[maxn][maxn]; int gx[4]

SGU 199. Beautiful People 二维LIS

第一维排序 第二维LIS #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int dp[100010]; int p[100010]; struct node { int x, y, id; }a[100010]; bool cmp(node a, node b) { if(a.x != b.x) return a.x < b.x; return a.y

hdu 4742 Pinball Game 3D(三维LIS&amp;cdq分治&amp;BIT维护最值)

Pinball Game 3D Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 688    Accepted Submission(s): 276 Problem Description RD is a smart boy and excel in pinball game. However, playing common 2D p

ACdream 1216——Beautiful People——————【二维LIS,nlogn处理】

Beautiful People Special Judge Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description The most prestigious sports club in one city has exactly N members. Each of its members

二维LIS

其实这题太水了 就是很简单的线段树维护cdq. 前对后影响用线段树维护一下即可. 具体看代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 20004 5 using namespace std; 6 int n,dp[N],ans; 7 struct node 8 { 9 int xi; 10 int yi; 11 int no; 12 bool friend ope

二维无序LIS ACdream1216 Beautiful People

传送门:点击打开链接 题意:告诉你n个人,每个人有个s和b连个值,要求从n个人中选出数量最多的人,使任意两个人(i,j)都有si<sj且bi<bj或者sj<si且bj<bi,要求输出选出数量最多的人,且输出是哪一些人,其中题目是spj. 思路:首先很容易想到DAG模型,但是这题的n<=100000,所以用DAG模型复杂度太高了.然后会想到LIS,可能就会想到用二维线段树去做. 其实仔细想想这道题,和普通的LIS还是有不一样的地方的.那就是他的顺序并不是给定的!!什么意思呢,虽