1.最长公共子序列
给出从 1 到 n 的两个排列 P1 和 P2,求它们的最长公共子序列。
输入格式
第一行是一个正整数 n。
接下来两行,每行为 n 个数,为自然数 1,2,…,n 的一个排列。
输出格式
一个数,即最长公共子序列的长度。
数据范围
1≤n≤10^5
输入样例
5
3 2 1 4 5
2 1 3 4 5
输出样例
4
因为给出的是一个1~n的排列,那么我们可以先将一号序列进行从小到大的排序,那么我们再将二号序列中的对应标号的元素也进行相应的排列,那么我们最后要求的结果其实也就是二号序列中的最长上升子序列(因为一号序列是单调递增的,二号序列中的元素要想和一号序列中的元素公共,那么这个子序列必然是上升的)
那么我们就可以用二分的方法很快得出答案了,完整代码如下:
#include<bits/stdc++.h>
using namespace std;
#define N 100005
int num1[N],num2[N],place[N];
vector<int>p;
bool check(int num){
if(p.empty()){
return true;
}
else{
if(num>p[p.size()-1]){
return true;
}
}
return false;
}
int main(){
int n,x;
cin>>n;
for(int i=1;i<=2;i++){
for(int j=1;j<=n;j++){
if(i==1){
cin>>x;
num1[j]=j;
place[x]=j;
}
else{
cin>>num2[j];
num2[j]=place[num2[j]];
}
}
}
for(int j=1;j<=n;j++){
if(check(num2[j])){
p.push_back(num2[j]);
}
else{
int point=lower_bound(p.begin(),p.end(),num2[j])-p.begin();
p[point]=num2[j];
}
}
cout<<p.size();
return 0;
}
2.喵喵序列
题目描述
给定一个含有 n 个整数的序列 a_1,a_2,…a_n,三个数 i,j,k 是可爱的当且仅当 i<j<k 且 a_i<a_j<a_k。
请你求出有多少组 i,j,k 是可爱的。
输入格式
第 1 行一个整数 n 表示序列元素个数。
第 2 行 n 个整数分别表示 a_1,a_2,…a_n。
输出格式
一行一个整数,表示所求数量。
样例输入
5
1 2 2 3 4
样例输出
7
样例说明
满足条件的有:(1,2,3),(1,2,4),(1,2,3),(1,2,4),(1,3,4),(2,3,4),(2,3,4),共 7 个。
数据范围
对于全部数据,有 1≤n≤3×104,0≤a_i<263
这道题我就直接引用这位大佬的题解吧,我是真的不会树状数组(qwq),我一开始还在傻傻的直接dp,但是显然这道题显然直接dp是不可能过的,必须要优化,所以就直接看题解吧。qwq
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
#define ll long long
#define mset(s,t) memset(s,t,sizeof(t