书接上回

一维偏序直接做、二维偏序套线段树或归并排序、三维偏序可以树套树或者 CDQ 套树,那四维偏序呢?可以 CDQ 套树套树。那五维偏序呢?可以发现,无论是 CDQ 分治还是树,都很难再继续嵌套,再写下去不但码量巨大,还巨难调,效率还相当低。树或 CDQ 嵌套 \(m\) 维偏序时间复杂度为 \(O(n\log^{m-1}n)\)。但是,我们使用 STL 的 bitset 可以在 \(O(\tfrac{n^2m}{w})\) 的优秀复杂度内解决这个问题。

前置知识:

bitset 的基本用法

最直观的做法是对每个维度开个 \(n\times m\) 的 \(01\) 矩阵,\(a_{i,j}\) 为 \(1\) 表示,在这个维度下 \(a_{i}\le a_{j}\),反之则是 \(a_{i}\gt a_{j}\)。如果我们要求每个维度都比 \(i\) 小的点的数量,直接把这 \(m\) 个维度的 \(01\) 矩阵的第 \(i\) 行与一下求 \(1\) 的个数就行了。

开 \(mn^2\) 的数组,bitset 也很难开的下,注意到单独的数组是没用的,所以在对每一维统计时直接与上之前的答案。对每一维排序,然后从小到大遍历物品,开一个临时 bitset 来存只考虑该维,值比当前位置小的位置,类似前缀的维护方法。注意初始化。排序时注意直接交换数组是 \(O(m)\) 的,所以只能对下标排序。一定要注意是 \(\le\) 还是 \(\lt\)。相当好写。

推个板子题

这题直接 bitset 预处理 \(m\) 维偏序,然后跑个相当显然的 \(O(n^2)\) dp 即可。注意为了保证只能从前面转移,dp 前按任意一维排个序,避免漏掉情况。比较卡常,写写快读快写。

教授の代码
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
namespace inout
{
#define super faster
#ifdef super
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif
template<typename tn> il void read(tn &x)
{
x=0;
register bool op=false;
register char ch=getchar();
while(ch<'0'||ch>'9')
{
op|=(ch=='-');
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
if(op)
{
x=~x+1;
}
}
template<typename tn> void writen(tn x)
{
if(x)
{
writen(x/10);
putchar(x%10|'0');
}
}
template<typename tn> il void write(tn x)
{
if(!x)
{
putchar('0');
return;
}
if(x<0)
{
putchar('-');
x=~x+1;
}
writen(x);
}
}using namespace inout;
int a,b,c[5005],qwer,ap[5005],ac;
bitset<5005>can[5005],now;
long long dp[5005],ans;
struct node
{
int val[505];
}pit[5005];
il bool cmp(int x,int y)
{
return pit[x].val[qwer]<pit[y].val[qwer];
}
int main()
{
read(a);
read(b);
for(ri i=1;i<=b;i++)
{
read(c[i]);
pit[i].val[0]=i;
can[i].set();
ap[i]=i;
}
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
read(pit[j].val[i]);
}
}
for(ri i=1;i<=a;i++)
{
qwer=i;
sort(ap+1,ap+1+b,cmp);
now.reset();
ri bg=0;
for(ri j=1;j<=b;j++)
{
if(pit[ap[j]].val[i]!=pit[ap[bg]].val[i])
{
while(bg!=j)
{
now.set(pit[ap[bg]].val[0]);
bg++;
}
bg=j;
}
can[pit[ap[j]].val[0]]&=now;
}
}
for(ri i=1;i<=b;i++)
{
ri h=pit[ap[i]].val[0];
for(ri j=1;j<i;j++)
{
ri k=pit[ap[j]].val[0];
if(can[h][k])
{
dp[h]=max(dp[h],dp[k]);
}
}
dp[h]+=c[h];
ans=max(ans,dp[h]);
}
write(ans);
return 0;
}

别 D 了,CDQ 分治会不了一点。

鲜花:bitset求解高维偏序的更多相关文章

  1. 【学习笔记】使用 bitset 求解较高维偏序问题

    求解五维偏序 给定 \(n(\le 3\times 10^4)\) 个五元组,对于每个五元组 \((a_i, b_i, c_i, d_i, e_i)\),求存在多少个 \(1\le j\le n\) ...

  2. [COGS2479 && COGS2639]高维偏序(CDQ分治,bitset)

    COGS2479:四维偏序. CDQ套CDQ CDQ:对a分治,对b排序,再对a打标记,然后执行CDQ2 CDQ2:对b分治,对c归并排序,对d树状数组. #include<cstdio> ...

  3. hihoCoder.1513.小Hi的烦恼(bitset 五维偏序)

    题目链接 五维偏序,对每一维维护bitset,表示哪儿为1(比它大),然后5个bitset与起来就能得到答案了. 具体实现可以用5*n个bitset,按排名搞个前缀和. 复杂度\(O(n^2/w)\) ...

  4. C++简单版BitSet求解大量数据是否存在莫个数

    #include <iostream> using namespace std; template<int N> class BitSet { public: BitSet() ...

  5. hiho#1513 : 小Hi的烦恼 五维偏序

    hiho#1513 : 小Hi的烦恼 五维偏序 链接 hiho 思路 高维偏序用bitset,复杂度\((\frac{n^2}{32})\) 代码 #include <bits/stdc++.h ...

  6. 浅谈CDQ分治与偏序问题

    初识CDQ分治 CDQ分治是一个好东西,一直听着dalao们说所以就去学了下. CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. ...

  7. 【2019.8.15 慈溪模拟赛 T2】组合数(binom)(卢卡斯定理+高维前缀和)

    卢卡斯定理 题目中说到\(p\)是质数. 而此时要求组合数向质数取模的结果,就可以用卢卡斯定理: \[C_x^y=C_{x\ div\ p}^{y\ div\ p}\cdot C_{x\ mod\ p ...

  8. HAOI2017 简要题解

    「HAOI2017」新型城市化 题意 有一个 \(n\) 个点的无向图,其中只有 \(m\) 对点之间没有连边,保证这张图可以被分为至多两个团. 对于 \(m\) 对未连边的点对,判断有哪些点对满足将 ...

  9. PKUSC2018训练日程(4.18~5.30)

    (总计:共66题) 4.18~4.25:19题 4.26~5.2:17题 5.3~5.9: 6题 5.10~5.16: 6题 5.17~5.23: 9题 5.24~5.30: 9题 4.18 [BZO ...

  10. SVM(支持向量机)的一点理解

    最近有被问到SVM的问题,不懂装懂,羞愧不已.百度有很多深入浅出介绍SVM的文章,我就不赘述了,这里写一点自己肤浅的理解. SVM的核心思想是把求解低维空间上的高维分类器转化为求解高维函数空间上的线性 ...

随机推荐

  1. 【牛客刷题】HJ8 合并表记录

    题目链接 这题最开始的想法就是用一个map来解决问题: func main() { num := 0 fmt.Scan(&num) a := 0 b := 0 m := make(map[in ...

  2. java如何保证一个方法只能执行一次

    我们经常会遇到一些情况需要某一个方法或者操作只执行一次,比如说配置信息加载,如果配置信息需要动态刷新,这个不在适用范围.下面列举几种方式 第一种 如果是web容器,可以使用servlet或者Liste ...

  3. springboot代码自动生成

    在项目开始阶段经常需要自动生成一批代码,如果使用了mybatis则可以使用mybatis plus就可以生成mybatis相关代码.不过经常项目中还有一些mvc代码需要生成,比如说前端代码.相关sql ...

  4. Notepad++作死,国产文本编辑器Notepad--发布

    作死的Notepad++ Notepad 和 Notepad++ 都是基于 Windows 的文本编辑器,通常用于编写和编辑纯文本文件. 这两个应用程序都是简单的轻量级程序,提供基本的文本编辑功能. ...

  5. Linux内核 自旋锁spin lock,教你如何用自旋锁让ubuntu死锁

    背景 由于在多处理器环境中某些资源的有限性,有时需要互斥访问(mutual exclusion),这时候就需要引入锁的概念,只有获取了锁的任务才能够对资源进行访问,由于多线程的核心是CPU的时间分片, ...

  6. 线性dp:大盗阿福(打家劫舍)

    大盗阿福 本题与leetcode198题--打家劫舍的题意一模一样,阅读完本文以后可以尝试以下题目 力扣题目链接) 题目叙述: 阿福是一名经验丰富的大盗.趁着月黑风高,阿福打算今晚洗劫一条街上的店铺. ...

  7. C++技能树

  8. SpringBoot 引入第三方 jar

    SpringBoot 引入第三方 jar 项目结构 -BCJS |--lib |--hsm-talos-1.0.1.jar |--src |--pom.xml step1 : 配置第三方 jar 为依 ...

  9. 解决向github上push报 error: failed to push some refs to 'xxxxx' 问题

    解决向github上push报 error: failed to push some refs to 'xxxxx' 问题 1.问题 向github上push 代码时,报  error: failed ...

  10. 第41天:WEB攻防-ASP应用&HTTP.SYS&短文件&文件解析&Access注入&数据库泄漏

    #ASP-中间件-CVE&短文件&解析&写权限 -HTTP.SYS(CVE-2015-1635) 1.漏洞描述 远程执行代码漏洞存在于 HTTP 协议堆栈 (HTTP.sys) ...