版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82925735
题目链接:点击这里
解题思路:将L,R看做平面直角坐标系坐标(x,y),将R变成-R,那么就变成x轴,y轴持续变小的最长连续序列.
用CDQ分治 + 树状数组,x轴排序,y轴用树状数组维护.先处理有半部分在根据有半部分得到左半部分.
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int mx = 5e4 + 10;
typedef long long ll;
int n,m;
int py[mx];
struct data
{
int fi,se;
}mln[mx],dp[mx];
struct node
{
int x,y;
int id;
bool operator < (node A)const
{
return x < A.x;
}
}s[mx],tep[mx];
void up(data& A,data B)
{
if(B.fi>A.fi) A = B;
else if(B.fi==A.fi&&B.se<A.se) A = B;
}
void add(int x,int id){
data tmp = {dp[id].fi,id};
while(x<=n){
up(mln[x],tmp);
x += x&(-x);
}
}
data Get(int x)
{
data ans = {0,0};
while(x){
up(ans,mln[x]);
x -= x&(-x);
}
ans.fi++;
return ans;
}
void clr(int x)
{
while(x<=n){
mln[x] = {0,0};
x += x&(-x);
}
}
int Rank(int x)
{
return lower_bound(py+1,py+m,x)-py;
}
void cdq(int l,int r)
{
int mid = (l+r)>>1;
if(l==r) return ;
int i = l,j = mid + 1;
cdq(mid+1,r);
for(int k=l;k<=r;k++) tep[k] = s[k];
sort(tep+l,tep+mid+1);
sort(tep+mid+1,tep+r+1);
while(i<=mid){
if(j<=r&&tep[i].x>=tep[j].x) add(Rank(tep[j].y),tep[j].id),j++;
else{
data pa = Get(Rank(tep[i].y));
up(dp[tep[i].id],pa);
i++;
}
}
for(j=mid+1;j<=r&&tep[mid].x>=tep[j].x;j++) clr(Rank(tep[j].y));
cdq(l,mid);
}
int main()
{
while(~scanf("%d",&n)){
m = 2;
for(int i=1;i<=n;i++){
scanf("%d",&s[i].x);
s[i].id = i;
dp[i].fi = 1,dp[i].se = 0;
}
for(int i=1;i<=n;i++){
scanf("%d",&s[i].y);
s[i].y = py[i] = -s[i].y;
}
sort(py+1,py+1+n);
for(int i=2;i<=n;i++) if(py[i]!=py[i-1]) py[m++] = py[i];
cdq(1,n);
data ans = {0,0};
for(int i=1;i<=n;i++) up(ans,dp[i]);
for(int i=1;i<=n;i++)
if(ans.fi==dp[i].fi){
printf("%d\n%d",ans.fi,i);
ans = dp[i];
break;
}
for(int i=ans.se;i;i=dp[i].se) printf(" %d",i);
puts("");
}
return 0;
}