cdq分治(陈丹琦分治)
//转自:http://blog.csdn.net/snowy_smile/article/details/49668689
/*
算法介绍之cdq分治: 其实cdq分治的思想与应用都能被很简单地描述——它是用来解决各种区间段转移问题[x->y(x<y)]的。
我们用f[x]表示位置x转移之后的结果,用solve(l,r)来传递完全限制在[l,r]范围内的状态转移,并且转移a->b一定有a<b
那么对于solve(l,r)
1,如果l==r,没有后续转移,程序结束。
2,求出m=(l+r)>>1;
3,solve(l,m);
4,传递[l,m]对[m+1,r]的贡献。
5,solve(m+1,r);
这样cdq分治就做完啦
*/ /*
【题意】
给你一个n(750)*m(750)的棋盘,每个格子(i,j)都有一种颜色c[i][j],
颜色范围是[1,top]中的整数,top取值范围是[1,5e5]。
对于一次跳跃A(y1,x1)->B(y2,x2),我们说这次跳跃是合法的,要求必须有:
1,y2>y1
2,x2>x1
3,c[y1][x1]!=c[y2][x2];
我们想要求出从(1,1)经过若干次跳跃之后到达(n,m)的方案数,mod(1e9+7) 【类型】
CDQ分治 【分析】
首先,我们可以构想一个暴力DP:
用f[i][j]表示从(1,1)到(i,j)的方案数
那么f[i][j]=∑f[u][v],u<i&&v<j&&c[u][v]!=c[i][j]
时间复杂度为O(n^2 m^2),想要通过这题,这还差得远。 思考1,
我们观察到,这道题中,颜色的范围不是1e9,而是5e5。为什么呢?
我们发现,相比较1e9,5e5这个范围的数组是开得下的,于是我们可以做计数处理,有助于我们维护答案。
(ps:如果颜色属于1e9范围,因为颜色种类最多只有n*m,所以其实我们可以离散化)
如果我们用d[x]表示颜色为从(1,1)走到当前处理范围颜色为x的点的方案数,
并用一个大的变量tot统计从(1,1)走到当前处理范围所有点的方案数之和。
那么当我们走到一个颜色为x的点时,就可以直接使用 tot-d[x] 来更新到达这个点的方案数。
这个思想有一定的价值,但是因为题目给出的1,2两个限制条件。
具体要通过什么途径保证d[]中处理的所有点都在它之间呢? 思考2,
区间问题的实现,很多时候我们都要引入整段考虑的思想。
这其实也就是CDQ分治的思想与具体实现。
我们想要更新从(1,1)走到行[l,r]范围格点的方案数。
而line[l,r]每个格子更新的来源,有两方面。
1,line[1,l-1]
2,line[l,r]内部
我们假设在处理[l,r]时,所有line[1,l-1]对line[l,r]的贡献已经生效。
于是现在只需要考虑来自于line[l,r]内部的贡献。
并且定义过程solve(l,r),用于解决[l,r]内部贡献的转移。 具体如何实现?
回归到这道题—— 1,如果l==r,那不会生成任何贡献,直接结束。
2,否则我们设m=(l+r)>>1;
接下来只要依次实现以下3个步骤,这道题就做完了。
(1),solve(l,m);
(2),从[l,m]向[m+1,r]转移贡献;
(3),solve(m+1,r);
于是,关键落在要如何实现(2)上——
此时,我们发现行关系已经是严格的小于关系,只需要使得列关系满足要求。如何使得?
因为问题不是在数轴上,而是在矩形中。
所以目前处理的区间是一个块,行数是[l,r],每行有m列。
我们现在是想要把[l,mid]的状态传递到[mid+1,r]。
发现只需要从左向右一列列枚举。
状态结果的传递在(mid,r])实现,状态来源的累计在[l,mid]实现。
就保证了行与列都是严格小于关系,这道题也就在O(nmlogn)的时间复杂度内解决了。 */
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxn = ;
int n,m,a[maxn][maxn],f[maxn][maxn],s[];
void add(int &x,int y){
x+=y;
x%=mod;
}
void solve(int l,int r){
if(l==r) return;
int mid=(l+r)>>;
//第一步:处理[l,mid]
solve(l,mid);
//第二步:处理[l.mid]->(mid,r]的转移
for(int i=l;i<=r;i++){
for(int j=;j<=m;j++){
s[a[i][j]]=;
}
}
int all=;
//从左到右逐列枚举,以及拓扑逆序,保证了列的小于关系
for(int j=;j<=m;j++){
//行累加只在[l,mid]展开,行转移在(mid,r]收集,保证了行的小于关系
for(int i=mid+;i<=r;i++) add(f[i][j],(all-s[a[i][j]]+mod)%mod);
for(int i=l;i<=mid;i++){
add(s[a[i][j]],f[i][j]);
add(all,f[i][j]);
}
}
//第三步:处理(mid,r]
solve(mid+,r);
}
int main(){
while(~scanf("%d%d%*d",&n,&m)){
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
memset(f,,sizeof(f));
f[][]=;
solve(,n);
printf("%d\n",f[n][m]);
}
return ;
}
cdq分治(陈丹琦分治)的更多相关文章
- CQD(陈丹琦)分治 & 整体二分——专题小结
整体二分和CDQ分治 有一些问题很多时间都坑在斜率和凸壳上了么--感觉斜率和凸壳各种搞不懂-- 整体二分 整体二分的资料好像不是很多,我在网上找到了一篇不错的资料: 整体二分是个很神的东西 ...
- 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)
[BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...
- BZOJ3672: [Noi2014]购票【CDQ分治】【点分治】【斜率优化DP】
Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的 ...
- 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
题目描述 给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...
- P3806 【模板】点分治1(题解)(点分治)
P3806 [模板]点分治1(题解)(点分治) 洛谷题目传送门 #include<iostream> #include<cstdlib> #include<cstdio& ...
- 洛谷P3806 【模板】点分治1 【点分治】
题目背景 感谢hzwer的点分治互测. 题目描述 给定一棵有n个点的树 询问树上距离为k的点对是否存在. 输入输出格式 输入格式: n,m 接下来n-1条边a,b,c描述a到b有一条长度为c的路径 接 ...
- 点分治Day2 动态树分治
蒟蒻Ez3real冬令营爆炸之后滚回来更新blog... 我们看一道题 bzoj3924 ZJOI2015D1T1 幻想乡战略游戏 给一棵$n$个点的树$(n \leqslant 150000)$ 点 ...
- 【Luogu】P3806点分治模板(点分治)
题目链接 wc听不懂lca讲的高等数学专场(一个字都听不懂),然后就自学了点分治. 点分治就是我先处理完跟根有关的东西,然后把根标记掉,把原树拆成若干个联通块,然后分别对每个联通块(每个小树)搞一模一 ...
- Acdream1157---Segments (CDQ分治)
陈丹琦分治~~~其实一些数据小的时候可以用二维或者多维树状数组做的,而数据大的时候就无力的题目,都可以用陈丹琦分治解决. 题目:由3钟类型操作:1)D L R(1 <= L <= R &l ...
随机推荐
- typedef 复杂函数指针
下面是三个变量的声明,我想使用typedef分别给它们定义一个别名,请问该如何做? >1:int *(*a[5])(int, char*); >2:void (*b[10]) (void ...
- 【Zookeekper】分布锁Curator
有序节点:假如当前有一个父节点为/lock,我们可以在这个父节点下面创建子节点:zookeeper提供了一个可选的有序特性,例如我们可以创建子节点“/lock/node-”并且指明有序,那么zooke ...
- Security基础(一):Linux基本防护措施、使用sudo分配管理权限、提高SSH服务安全
一.Linux基本防护措施 目标: 本案例要求练习Linux系统的基本防护措施,完成以下任务: 修改用户zhangsan的账号属性,设置为2015-12-31日失效(禁止登录) 锁定用户lisi的账户 ...
- [Repost] 探寻C++最快的读取文件的方案
作者:BYVoid(https://www.byvoid.com/zhs/blog/fast-readfile) 版权协议:CC BY-NC-SA 3.0 Unported 在竞赛中,遇到大数据时,往 ...
- Vuetify按需加载配置
自己配置vuetify按需加载的步骤,在此记录: 执行npm install vuetify –save 或 yarn add vuetify添加vuetify添加依赖执行npm install -- ...
- 【从0到1,搭建Spring Boot+RESTful API+Shiro+Mybatis+SQLServer权限系统】02、创建新的SpringBoot项目
1.创建项目 得到项目架构 2.测试项目Web功能 默认端口为8080,运行后,输入localhost:8080/index即可访问到网页 到这里,项目构建成功!
- MySQL允许远程登录配置
1.查看user表mysql> use mysqlReading table information for completion of table and column namesYou ca ...
- 46、tensorflow入门初步,手写识别0,1,2,3,4,5,6
1.使用tensorflow的SoftMax函数,对手写数字进行识别 Administrator@SuperComputer MINGW64 ~ $ docker run -it -p 8888:88 ...
- Linux应急响应基础
文件排查 敏感目录文件分析 tmp目录 命令目录 /usr/bin /usr/sbin 开机启动项 /etc/init.d /etc/init.d是/etc/rc.d/init.d的软链接 文件时间 ...
- Python 文件及文件夹处理
import os,shutil def getfilelist(filepath): filelist = os.listdir(filepath) # 获取filepath文件夹下的所有的文件 # ...