「JOISC 2016 Day 1」俄罗斯套娃
「JOISC 2016 Day 1」俄罗斯套娃
传送门
题解
首先不难发现题目要求的是\(H\)有序下的\(R\)的最长不增子序列长度.
这个东西不难用离线排序然后树状数组维护.
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
typedef pair<int,int> pii;
#define mp make_pair
inline int gi()
{
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=400010;
int n,Q,ans[N],c[N],tot,o[N];
int lowbit(int x){return x&(-x);}
void add(int x,int d){while(x<=tot){c[x]=max(c[x],d);x+=lowbit(x);}}
int qry(int x){int ret=0;while(x){ret=max(ret,c[x]);x^=lowbit(x);}return ret;}
struct item{int r,h;}p[N];
struct ques{int a,b,id;}q[N];
bool operator<(const item a,const item b){return a.r>b.r||(a.r==b.r&&a.h<b.h);}
bool operator<(const ques x,const ques y){return x.a>y.a;}
int main()
{
n=gi();Q=gi();
for(int i=1;i<=n;i++){int r=gi(),h=gi();p[i]=(item){r,h};o[++tot]=h;}
sort(p+1,p+n+1);
for(int i=1;i<=Q;i++){int a=gi(),b=gi();q[i]=(ques){a,b,i};o[++tot]=b;}
sort(q+1,q+Q+1);int pos=1,mx=1e9+10;
sort(o+1,o+tot+1);tot=unique(o+1,o+tot+1)-o-1;
for(int i=1;i<=n;i++)p[i].h=lower_bound(o+1,o+tot+1,p[i].h)-o;
for(int i=1;i<=Q;i++)q[i].b=lower_bound(o+1,o+tot+1,q[i].b)-o;
for(int i=1;i<=n;i++)
{
// printf("%d:%d %d\n",i,p[i].r,p[i].h);
mx=min(mx,p[i].r);
while(pos<=Q&&q[pos].a>mx){ans[q[pos].id]=qry(q[pos].b);pos++;}
int l=qry(p[i].h)+1;add(p[i].h,l);
}
while(pos<=Q){ans[q[pos].id]=qry(q[pos].b);pos++;}
for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
return 0;
}