俄罗斯套娃(JOISC 2016 Day 1)

俄罗斯套娃(JOISC 2016 Day 1)

题目描述

你开了一家卖俄罗斯套娃的店。因此,你向厂家订购了 \(N\)个俄罗斯套娃,这些娃娃被编号为 \(1\)\(N\),其中第 \(i\) 个套娃是一个的直径为 \(R_i\) 高度为 \(H_i\) 的直♂柱体 。每个俄罗斯套娃都只能套高和直径严格比他小的套娃。同时只要满足条件,俄罗斯套娃可以嵌套多次。

有一天,你收到了厂家的来电,告诉你你预定的 \(N\) 个娃娃不能一次性全部做完。所以第一批只会送达直径大于等于 \(A\) 并且高度小于等于 \(B\) 的所有套娃。你需要预先安排出一个方案,使送来的套娃经过若干次嵌套后,没有被套的套娃数量最小。

由于厂家经常搞大新闻,所以他会改变 \(A\)\(B\) 的值,总共 \(Q\) 次,因此你需要对每对 \((A,B)\) 都作出回答,询问之间互不干扰。

输入

第一行有两个整数 \(N\)\(Q\) ,表示套娃的个数和 \((A,B)\) 的对数;
之后的 \(N\) 行,每行两个数 \(R_i\)\(H_i\) 表示第$ i$ 个数的直径和高度;
之后的 \(Q\) 行,每行两个数 \(A_i\)\(B_i\) 表示第 \(i\) 个询问, \(A_i\)\(B_i\) 的意思如上所示。

输出

一个整数,表示符合条件的方案个数。

思路

重要结论

这题每个套娃都是二维的,于是可以用\(xy​\)坐标轴表示所有的套娃,任意一个点只要在另一个点的右上方就可以把那点(娃娃)装进去

image

(横坐标为R,纵坐标为H)

这题根据人类的智慧可以得到

(直接)甩结论:最少的没被套的娃娃个数=最长的\(R\)递增,\(H\)递减的序列长度

这个可以感性理解一下,所有不在该序列上的点都必定会在一个点的右上方,所以就相当于所有多出来的点都是可以被装进另一个点中的。

离线+离散

知道这个后就去考虑每个询问,对于每个询问,若逐个计算每次的答案,用一个树状数组其中一维,显然要将一维进行离散。那么剩下的一位直接考虑进行离线处理,那么复杂度就被用优化成\(O((n+q)log_(n+q))\),可以开两个数组分别表示娃娃和询问,不过放一个数组里面一起排序会简单一些,不过注意在遇到询问和娃娃的两个值完全相同时,一定要先更新娃娃在回答询问(当时就被这个卡了。。。)

代码

#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=(l),END=(r);i<=END;i++)
#define DOR(i,r,l) for(int i=(r),END=(l);i>=END;i--)
#define loop(i,n) for(int i=0,END=(n);i<END;i++)
#define sf scanf
#define pf printf
#define pb push_back
#define pii pair<int,int>
#define R first
#define H second
#define mms(a,x) memset(a,x,sizeof a)
using namespace std;
typedef long long ll;
typedef long double db;
template<typename A,typename B>inline void chkmax(A &x,const B y){if(x<y)x=y;}
template<typename A,typename B>inline void chkmin(A &x,const B y){if(x>y)x=y;}
const int N=2e5+5;
int n,q;
pii doll[N];
struct Pt2{
    struct node{
        int x,y,id;
        bool operator<(const node &A)const{
            if(x!=A.x)return x>A.x;
            if(y!=A.y)return y<A.y;
            return id<A.id;
        }
    }A[N<<1];
    int b[N<<1],ans[N],ct;
    struct Binary_Indexed_Tree{
        #define lowbit(x) (x&-(x))
        static const int M=4e5;
        int c[N<<1];
        void update(int x,int val){while(x<=M)chkmax(c[x],val),x+=lowbit(x);}
        int query(int x){int ret=0;while(x)chkmax(ret,c[x]),x-=lowbit(x);return ret;}
    }BIT;
    void solve(){
        FOR(i,1,n)b[++ct]=doll[i].H,A[i]=(node){doll[i].R,doll[i].H,0};;
        FOR(i,1,q){
            sf("%d%d",&A[n+i].x,&A[n+i].y);
            A[n+i].id=i,b[++ct]=A[n+i].y;
        }
        sort(b+1,b+ct+1);
        ct=unique(b+1,b+ct+1)-b-1;
        sort(A+1,A+n+q+1);
        FOR(i,1,n+q)A[i].y=lower_bound(b+1,b+ct+1,A[i].y)-b;
        FOR(i,1,n+q){
            if(A[i].id)ans[A[i].id]=BIT.query(A[i].y);
            else {
                int nw=BIT.query(A[i].y);
                BIT.update(A[i].y,nw+1);
            }
        }
        FOR(i,1,q)pf("%d\n",ans[i]);
    }
}Pt_2;

猜你喜欢

转载自www.cnblogs.com/Heinz/p/10683381.html