论如何优雅的用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)....

尽管看上去很慢但是。。

转载于:https://www.cnblogs.com/Acheing/p/7236213.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值