几道很Interesting的偏序问题
若干道偏序问题(STL,分块)
找了4道题目
BZOJ陌上花开(权限题,提供洛谷链接)
Cogs2479偏序
Cogs2580偏序II
Cogs2639偏序++
作为一个正常人,肯定先看三维偏序
做法很多呀
首先,由于
智商不够数据结构来补 $ \ \ \ \ \ \ $--菊开
所以我们用最傻逼的数据结构来做这道题目
第一维:排序
第二维:树状数组
第三维:平衡树
于是乎,我们得到了一个复杂度为\(O(nlog^2n)\)的做法
并且常数巨大
这个做法到这里去看
第二种做法
CDQ分治
相信大家都会逆序对的求法
可以归并排序求逆序对
逆序对相当于是一个二维偏序
第一维就相当于它的位置
第二维就是值
每次归并排序的时候相当于分成了两部分
只有左侧的部分才能对右侧的部分产生贡献
这里同理,第一维排序
第二维类似于归并排序就行合并
同时一遍归并一边计算第三维
是不是想到了逆序对还可以用树状数组来求
所以这里一样的,
第三维用一个BIT来求就行了
这种做法看这里
恩,三维偏序没了
现在看Cogs的【偏序】
四维偏序模板题
可以顺着三维偏序来思考
既然多了一维
我就多套个CDQ分治呀
那不就是CDQ分治套树套树
或者CDQ分治套CDQ分治加树状数组
复杂度\(O(nlog^3n)\)
好像也可以诶。。。
好好好
我们继续
Cogs【偏序II】
不就是个五维偏序吗
CDQ套CDQ套CDQ
或者CDQ套CDQ套树套树
没毛病,时间复杂度\(O(nlog^4n)\)
可以做可以做,没问题的
那,我们继续
Cogs【偏序++】
七维偏序呀
CDQ套CDQ套CDQ套CDQ套CDQ
或者CDQ套CDQ套CDQ套CDQ套树套树
时间复杂度\(O(nlog^6n)\)
绝对跑不过的
而且给定的维数是K
你还得分类讨论,看着就是不可做的题目呀。。。
怎么办怎么办。。。
首先,请允许我orz大佬 ——中国翅王

FHR的做法的复杂度:\(O(n\sqrt n)\)
首先,我们知道
一个向量的偏序数量
等于它每一维的偏序数量的交集的大小
所以,按照每一维排序之后
我们就可以求出比每一维小的集合
然后求一个交集就行了
但是,暴力求,,,不现实吧。
而且交集也不好求呀
所以,来搞个\(bitset\)
STL大法好
但是,这样不就是\(O(n^2)\)的暴力吗???
没错,我们再来一发——分块大法好
分块之后就可以把一个\(n\)变成\(\sqrt n\)
于是复杂度就降到了\(O(n \sqrt n)\)
美滋滋
献上丑陋的代码(【偏序++】)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<bitset>
#include<queue>
using namespace std;
#define MAX 45000
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,blk;
bitset<45000> bs[15][250];
pair<int,int> val[15][MAX];
int bl[MAX],bll[MAX],blr[MAX];
int K,num;
long long Ans;
int f[15][MAX];
int find(int k,int x)
{
int l=1,r=n,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(val[k][mid].first<=x)ans=x,l=mid+1;
else r=mid-1;
}
return ans;
}
inline bitset<MAX> getbst(int p,int x)
{
bitset<MAX> ans;ans.reset();
int pp=find(p,x);
if(pp<=0)return ans;
int pre=(pp-1)/blk;
int st=pre*blk+1;
ans=bs[p][pre];
for(int i=st;i<=pp;++i)ans.set(val[p][i].second);
return ans;
}
void Solve()
{
bitset<MAX> ans;ans.reset();
for(int i=1;i<=n;++i)
{
ans.set();
for(int j=1;j<=K;++j)
ans&=getbst(j,f[j][i]);
Ans+=ans.count()-1;
}
}
int main()
{
freopen("partial_order_plus.in","r",stdin);
freopen("partial_order_plus.out","w",stdout);
n=read();blk=sqrt(n);K=read()+1;
for(int i=1;i<=n;++i)val[1][i]=make_pair(f[1][i]=i,i);
for(int j=2;j<=K;++j)
for(int i=1;i<=n;++i)
val[j][i]=make_pair(f[j][i]=read(),i);
for(int i=1;i<=K;++i)sort(&val[i][1],&val[i][n+1]);
for(int i=1;i<=n;++i)
bl[i]=(i-1)/blk+1;num=bl[n];
for(int i=1;i<=num;++i)
bll[i]=(i-1)*blk+1,blr[i]=i*blk;blr[num]=n;
for(int j=1;j<=K;++j)
for(int i=1;i<=num;++i)
{
bs[j][i]=bs[j][i-1];
for(int k=bll[i];k<=blr[i];++k)
bs[j][i][val[j][k].second]=1;
}
Solve();
printf("%lld\n",Ans);
return 0;
}
几道很Interesting的偏序问题的更多相关文章
- 两道很好的dp题目【4.29考试】
A 问题描述: 对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用I表示,反之这个位置是下降的,用D表示.如排列3,1,2,7,4,6,5可以表示为DIIDID. 现 ...
- 【学习笔记】使用 bitset 求解较高维偏序问题
求解五维偏序 给定 \(n(\le 3\times 10^4)\) 个五元组,对于每个五元组 \((a_i, b_i, c_i, d_i, e_i)\),求存在多少个 \(1\le j\le n\) ...
- 高斯消元几道入门题总结POJ1222&&POJ1681&&POJ1830&&POJ2065&&POJ3185
最近在搞高斯消元,反正这些题要么是我击败了它们,要么就是这些题把我给击败了.现在高斯消元专题部分还有很多题,先把几道很简单的入门题总结一下吧. 专题:http://acm.hust.edu.cn/vj ...
- 我也不知道什么是"莫比乌斯反演"和"杜教筛"
我也不知道什么是"莫比乌斯反演"和"杜教筛" Part0 最近一直在搞这些东西 做了将近超过20道题目吧 也算是有感而发 写点东西记录一下自己的感受 如果您真的 ...
- Codeforces Round #415 (Div. 2) 翻车啦
A. Straight «A» time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- ZOJ Problem Set - 1006 Do the Untwist
今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...
- wex5 实战 单页模式下的多页面数据同步
在wex5官方教程中,关于多页模式与单页模式进行了对比.两者最大的区别在于: 1 web加载速度,单页模式快于多页模式 2 多页模式对加载机制进行了预加载,一次加载之后再次加载,就会加快. 但是,由 ...
- 【BZOJ-3306】树 线段树 + DFS序
3306: 树 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 792 Solved: 262[Submit][Status][Discuss] De ...
- hdu Remainder
这道题是道很明显的bfs题.因为对数论没什么研究 ,所以这道题目里的两个关键点并不知道,看了别人的题解才知道 . 1.为避免取模后出现负数,采用:x%y=(x%y+y)%y 2.全部采用对m*k取模后 ...
随机推荐
- 正负样本比率失衡SMOTE
正负样本比率失衡SMOTE [TOC] 背景 这几天测试天池的优惠券预测数据在dnn上面会不会比集成树有较好的效果,但是正负样本差距太大,而处理这种情况的一般有欠抽样和过抽样,这里主要讲过抽样,过抽样 ...
- 利用ajax获取网页表单数据,并存储到数据库之一(使用JDBC)
所谓JDBC就是利用java与数据库相连接的技术,从数据库获取既有的信息或者把网页上的信息存储到数据库. 这里简单的介绍公司的一个小项目中的一部分,由于代码较多,所以用图片形式进行展示.源码请查看源码 ...
- WinForm中使用DDE技术(含源码)
提起DDE技术,相信很多人不知道是啥东东,尤其是90后的程序员们.不过,有时候这个东西还是有用处的,用一句话可以总结:实现Winform程序间的通信.比如:两个Winform程序A和B需要实现通信,用 ...
- 框架学习笔记之Maven简介和配置
一.什么是Maven?★Maven可翻译为“知识的积累”.“专家”.“内行”,它是一个跨平台的项目管理工具.★Maven提供了开发人员构建一个完整的生命周期框架,开发团队可以自动完成项目的基础工具建设 ...
- java-redis字符类数据操作示例(一)
对于大部分程序猿来讲,学习新知识重在编码实践,于我也是这样.现在初识redis,一直看文章难免感觉是浮光掠影,印象不深.所以间隙中,将自己的测试代码整理成博客,旨在加深记忆并提醒自己对待编程要用心沉下 ...
- Tomcat启动出现:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringMvc]]解决办法
严重: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component ...
- Android 文字过长TextView如何自动截断并显示成省略号
当用TextView来显示标题的时候,如果标题内容过长的话,我们不希望其换行显示,这时候我们需要其自动截断,超过的部分显示成省略号. 如下图所示,标题过长,自动换行了,显示不是很好看. 这时候我们需要 ...
- WPF文本框只允许输入数字
XAML代码 < TextBox Height="23" HorizontalAlignment="Left" Margin="100,5, ...
- const char *p;和char * const p的区别
const char *p; const修饰*p,所以*p是一个常量,不可修改. char* const p; const修饰p,所以指针p是一个常量,不可修改. #include< ...
- (二十七)mongodb操作学习
在不使用mongodbVUE图形界面工具的情况下,打开数据库和集合后,如果要: 插入一条字段名为name,内容为java的记录,可以写成x={name:"java"};,然后 ...