论如何优雅的用bitset来求四维偏序

四维偏序。。

就是给你一个四维集合。再给你一些询问,请你求出a[i].x1<=ask.x1&&a[i].x2<=ask.x2&&a[i].x3<=ask.x3&&a[i].x4<=ask.x4的个数。。

集合大小<=30000

询问个数<=30000

然后怎么做呢??

其实很简单只要排序+cdq+树状数组套平衡树什么的就行了

qnmd老子不会。。

这时!

神器来了!

那就是bitset!

众所周知,bitset能存一堆二进制位每一位的状态,而且,bitset和bitset之间是可以进行&操作的

也就是说,我们每次可以对第i位排个序,在判断第i个集合是否满足询问条件,bitset&一下就好了!

放上代码

#include<cmath>
#include<cstdio>
#include<bitset>
#include<algorithm>
#define N 40000
#define eps 1e-8
using namespace std;
int i,j,k,n,m,x,y,t;
struct data{double x1,x2,x3,x4;int id,p;}p[N],q[N],pq[N+N];
bitset<N> ans[N],w;
bool same(double a,double b){return fabs(a-b)<eps;}
bool cmp1(const data&a,const data&b){return same(a.x1,b.x1)?a.p>b.p:a.x1<b.x1-eps;}
bool cmp2(const data&a,const data&b){return same(a.x2,b.x2)?a.p>b.p:a.x2<b.x2-eps;}
bool cmp3(const data&a,const data&b){return same(a.x3,b.x3)?a.p>b.p:a.x3<b.x3-eps;}
bool cmp4(const data&a,const data&b){return same(a.x4,b.x4)?a.p>b.p:a.x4<b.x4-eps;}
int main(){
    scanf("%d",&n);
    for (i=1;i<=n;i++){scanf("%lf%lf%lf%lf",&p[i].x1,&p[i].x2,&p[i].x3,&p[i].x4);p[i].id=i;p[i].p=1;}
    scanf("%d",&m);
    for (i=1;i<=m;i++){scanf("%lf%lf%lf%lf",&q[i].x1,&q[i].x2,&q[i].x3,&q[i].x4);q[i].id=i;q[i].p=0;}
    for (i=1;i<=m;i++)ans[i].set();
    //-----------------------------------------------------------------
    for (i=1;i<=n;i++)pq[i]=p[i];
    for (i=1;i<=m;i++)pq[n+i]=q[i];
    sort(pq+1,pq+1+n+m,cmp1);
    w.reset();
    for (i=1;i<=n+m;i++)if (pq[i].p)w[pq[i].id]=1;else ans[pq[i].id]&=w;
    //-----------------------------------------------------------------
    for (i=1;i<=n;i++)pq[i]=p[i];
    for (i=1;i<=m;i++)pq[n+i]=q[i];
    sort(pq+1,pq+1+n+m,cmp2);
    w.reset();
    for (i=1;i<=n+m;i++)if (pq[i].p)w[pq[i].id]=1;else ans[pq[i].id]&=w;
    //-----------------------------------------------------------------
    for (i=1;i<=n;i++)pq[i]=p[i];
    for (i=1;i<=m;i++)pq[n+i]=q[i];
    sort(pq+1,pq+1+n+m,cmp3);
    w.reset();
    for (i=1;i<=n+m;i++)if (pq[i].p)w[pq[i].id]=1;else ans[pq[i].id]&=w;
    //-----------------------------------------------------------------
    for (i=1;i<=n;i++)pq[i]=p[i];
    for (i=1;i<=m;i++)pq[n+i]=q[i];
    sort(pq+1,pq+1+n+m,cmp4);
    w.reset();
    for (i=1;i<=n+m;i++)if (pq[i].p)w[pq[i].id]=1;else ans[pq[i].id]&=w;
    for (i=1;i<=m;i++)printf("%d\n",ans[i].count());
    return 0;
}

分隔符是为了分开四次排序。。

复杂度是O(n*m/32)....

尽管看上去很慢但是。。

时间: 2024-08-04 02:49:23

论如何优雅的用bitset来求四维偏序的相关文章

Gym - 100342J:Triatrip(Bitset加速求三元环的数量)

题意:求有向图里面有多少个三元环. 思路:枚举起点A,遍历A可以到的B,然后求C的数量,C的数量位B可以到是地方X集合,和可以到A的地方Y集合的交集(X&Y). B点可以枚举,也可以遍历.(两种都试过,区别不大.) 枚举代码: #include<cstdio> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algori

HihoCoder - 1513 bitset处理五维偏序

题意:给出\(n<3e4\)个有序组\((a,b,c,d,e)\),求对第\(i\)个有序组有多少个\(j\)满足\((a_j<a_i,b_j<b_i,c_j<c_i,d_j<d_i,e_j<e_i)\) 五维偏序问题按套路来可以排序+树套树套树套树(打死 然而这是显然连\(O(n^2)\)暴力都不如的 可是题目给4s,\(O(n^2)\)是不可能的,但在神奇的bitset加持下\(O(5*n^2/32)\)的时空复杂度是可以卡过去的! 用bitset表示集合,\(bi

hdu5618(cdq分治求三维偏序)

题意:给n(n<=100000)个点,坐标为(xi,yi,zi)(1<=xi,yi,zi<=100000),定义一个点A比一个点B小,当且仅当xA<=xB,yA<=yB,zA<=zB.求对于每个点,有多少个点比它小. 分析: 首先肯定按照x递增顺序排个序 接下来就是每次往平面插入一个点,求这个点左下方已经有多少个点,这可以用二维树状数组来搞,但是很明显会爆空间,不可以接受(当然树套树也是不可以的) 可以考虑对第二维cdq分治 对于一个区间[l,r],先递归区间[l,mi

SPOJ:Another Longest Increasing Subsequence Problem(CDQ分治求三维偏序)

Given a sequence of N pairs of integers, find the length of the longest increasing subsequence of it. An increasing sequence A1..An is a sequence such that for every i < j, Ai < Aj. A subsequence of a sequence is a sequence that appears in the same

【动态规划】【滚动数组】【bitset】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem J. Terminal

有两辆车,容量都为K,有n(10w)个人被划分成m(2k)组,依次上车,每个人上车花一秒.每一组的人都要上同一辆车,一辆车的等待时间是其停留时间*其载的人数,问最小的两辆车的总等待时间. 是f(i,j)表示前i组,j个人是否可行.w(i)表示第i组的人数. if f(i,j)==1 then f(i+1,j+w(i+1))=1. 这是个bitset可以做的事情,每次左移以后或上f(i-1)的bitset即可.其实可以滚动数组. 然后每更新一次bitset,求一下其最左侧的1的位置,就是对于第一辆

东北育才 d1t1 优雅的序列

优雅的序列 grace.cpp 题目描述 设一个含有n个数的序列的优雅度为满足ai<ai+1(1≤i<n)的i的个数.现在给出一个含有n个数的序列,小X想要将这n个数调整顺序,使得新序列的优雅度最大.同样喜欢优雅的你,能否求出这个最大的优雅度呢? 输入格式: 第1行:一个整数n 第2行:n个整数,表示原始序列 输出格式: 输出1个整数,为新序列的最大优雅度 样例输入 样例输出 5 1 3 2 4 1 3 样例解释 排列方式不唯一,一种可行的排列方式为1.2.1.3.4,优雅度为3.可以通过穷举

HDU - 5126: stars (求立方体内点数 CDQ套CDQ)

题意:现在给定空空的三维平面,有加点操作和询问立方体点数. 思路:考虑CDQ套CDQ.复杂度是O(NlogN*logN*logN),可以过此题. 具体的,这是一个四维偏序问题,4维分别是(times,x,y,z):我们知道cdq可以求出t<=T,x=X,y<=Y,在套一层就可以z<=Z了.那么一个立方体,我们拆为8个点来容斥. 然后现在的问题就是,求出(0,0,0)到(x,y,z)的点数. 第一维T已经默认排序了,我们先对X分治. 把所有问题分成两块,并且把左边这块标记o=-1,右边的标

XJOI-NOIP2015提高组模拟题1 day1

其实这只是一道题的题解= =: 博主太弱不会T1T3: 然而我还是要吐槽一下,T2难道你们就没有一点写数据结构的心情吗! T1: 留坑(不太可能填): T2: 题意: 给出大小为n的一个四维点集,和m次询问: 每次询问给出一个点,求四维坐标均小于等于这个点的集合大小: n,m<=30000: 题解: 看到这题的第一反应是排序乱搞,noip难度应该随便玩玩就过了嘛(笑): 但是仔细看看不是这么回事! bzoj有一道题叫陌上花开--然而那个是三维的: 回忆一下,PoPoQQQ让我们搞排序+CDQ分治

使用RxBinding处理控件异步调用

欢迎Follow我的GitHub, 关注我的CSDN. RxBinding是Rx中处理控件异步调用的方式, 也是由Square公司开发, Jake负责编写. 通过绑定组件, 异步获取事件, 并进行处理. 编码风格非常优雅. 让我来讲解一下如何使用, 本文含有代码示例. Github下载, 关注RxBinding部分, 其余参考. 1. 依赖 除了RxJava, 再添加RxBinding的依赖. // RxBinding compile 'com.jakewharton.rxbinding:rxb