hdu 5324 - CDQ分治 + 树状数组

版权声明:欢迎随便转载。 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;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/82925735
今日推荐