今天晚上,想到自己的线段树专题中的题还未码完。
此时,我看了看手边安详的作业,痛下决心,晚上熬夜补吧(唉~ 竞赛生的艰难啊 ~)。
于是,便有了我今日的博客。
洛谷题面 bzoj3939 Cow Hopscotch

以上链接便是相应的题目;

拿到这道题,我们可以分析一下题目性质。

对于点(x,y)点(x,y)点(x,y)来说,能跳到它上面的点的集合为:
∑i=1x−1∑j=1y−1(i,j)(a[i][j]!=a[x][y],a数组代表编号)\sum\limits^{x-1}_{i=1}\sum\limits^{y-1}_{j=1}(i,j)(a[i][j]!=a[x][y],a数组代表编号)i=1∑x−1​j=1∑y−1​(i,j)(a[i][j]!=a[x][y],a数组代表编号)。

遇到这种在二维数组内求解方案数的题目,我们会很自然而然地想到区间DP,更何况n,m的数值还比较小。最暴力的方法,便是四重循环,在外面两层枚举行与列,在内两层枚举1~ x-1, 1 ~ y-1。然后,将符合条件的f[i][j]赋值到f[x][y]上。

但是,n4n^4n4的时间复杂度,肯定会爆。(但据说数据太水了,n4n^4n4的算法都可以过。)

那么,我们就需要线段树这种数据结构来维护了。

根据二维前缀和思想,我们可以再开一个数组sum,记录f(也就是DP数组)的前缀和。
那么,对于当前的f[x][y]f[x][y]f[x][y],我们可以用sum[x−1][y−1]sum[x-1][y-1]sum[x−1][y−1]减去∑i=1x−1∑j=1y−1f(i,j)\sum\limits^{x-1}_{i=1}\sum\limits^{y-1}_{j=1}f(i,j)i=1∑x−1​j=1∑y−1​f(i,j),且a[i][j]=a[x][y]a[i][j]=a[x][y]a[i][j]=a[x][y]。

前缀和的问题我们不用考虑了,剩下的就是怎么快速求:
∑i=1x−1∑j=1y−1f(i,j)(a[i][j]=a[x][y])\sum\limits^{x-1}_{i=1}\sum\limits^{y-1}_{j=1}f(i,j)(a[i][j]=a[x][y])i=1∑x−1​j=1∑y−1​f(i,j)(a[i][j]=a[x][y])。

思考一下,每个点的编号最大是n∗mn*mn∗m,且n,m都是比较小的常数。那么,我们可以对每个编号开一个线段树,用来记录从上到下,编号为i的点的f值。

那么,对于当前的点(x,y)(x,y)(x,y), ∑i=1x−1∑j=1y−1f(i,j)(a[i][j]=a[x][y])\sum\limits^{x-1}_{i=1}\sum\limits^{y-1}_{j=1}f(i,j)(a[i][j]=a[x][y])i=1∑x−1​j=1∑y−1​f(i,j)(a[i][j]=a[x][y])就可以在a[x][y]所代表的线段树中查找区间(1,y−1)(1,y-1)(1,y−1)的值(因为我们是按行开始从上往下进行处理的,所以x行以下的数就不会存进去)。

思路便是如此。

时间复杂度为:O(n∗m∗lognm)O(n*m*log nm)O(n∗m∗lognm)

代码实现如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo=1e9+7;
const int M=1e6+10;
struct ao
{int ls,rs;int num;#define ls(x) tree[x].ls#define rs(x) tree[x].rs#define num(x) tree[x].num
}tree[M*15];
int n,m,k,a[800][800],cnt,root[600000];
ll f[800][800],sum[800][800];
void change(int &p,int l,int r,int wei,int val)
{if(!p) p=++cnt;num(p)+=val;num(p)%=mo;if(l==r) return;int mid=l+r>>1;if(wei<=mid) change(ls(p),l,mid,wei,val);else change(rs(p),mid+1,r,wei,val);
}
ll cz(int p,int l,int r,int L,int R)
{if(!p) return 0;if(l>=L&&r<=R){return num(p)%mo;}ll ans=0;int mid=l+r>>1;if(L<=mid) ans+=cz(ls(p),l,mid,L,R)%mo;if(R>mid) ans+=cz(rs(p),mid+1,r,L,R)%mo;return ans%mo;
}
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);}f[1][1]=sum[1][1]=1;change(root[a[1][1]],1,m,1,f[1][1]);for(int i=2;i<=n;i++)sum[i][1]=1;for(int i=2;i<=m;i++)sum[1][i]=1;for(int i=2;i<=n;i++){for(int j=2;j<=m;j++) f[i][j]=(sum[i-1][j-1]%mo-cz(root[a[i][j]],1,m,1,j-1)%mo+mo)%mo;;for(int j=2;j<=m;j++) sum[i][j]=(sum[i-1][j]%mo+sum[i][j-1]%mo+f[i][j]-sum[i-1][j-1]%mo+mo)%mo;for(int j=2;j<=m;j++) change(root[a[i][j]],1,m,j,f[i][j]);}cout<<f[n][m];return 0;
}

[bzoj3939_Usaco2015 Feb]Cow Hopscotch(线段树维护DP)相关推荐

  1. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  2. YBTOJ:采矿战略(线段树维护dp、树链剖分)

    文章目录 题目描述 解析 代码 题目描述 所谓线段树维护dp,就是在线段树上维护dp (逃) 解析 把树剖一下后就变成了区间问题 考虑建一棵线段树,每一个结点都是一个背包 这样就能区间查询,也能带修了 ...

  3. 【BZOJ2164】采矿 树链剖分+线段树维护DP

    [BZOJ2164]采矿 Description 浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略.这个城市可以看成一棵有n个节点的有根树,我们把每个节点用1到n ...

  4. 兰州大学第一届 飞马杯 ★★飞马祝福语★★ 线段树维护dp(动态dp)

    传送门 文章目录 题意: 思路: 题意: 给你一个串,每次将区间都修改为某一个字母,问最终包含多少个FeiMaFeiMaFeiMa子序列. 思路: 首先暴力修改肯定是不行的,复杂度nqnqnq. 如果 ...

  5. BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...

  6. 【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)

    4422: [Cerc2015]Cow Confinement Time Limit: 50 Sec  Memory Limit: 512 MB Submit: 61  Solved: 26 [Sub ...

  7. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  8. 【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/E?&headNav=acm 来源:牛客网 Given a maze with N rows an ...

  9. Codeforces Round #603 (Div. 2) E. Editor 线段树维护括号序列

    传送门 文章目录 题意: 思路: 题意: 思路: 首先一个括号序列合法的条件可以转化成两个(左括号代价为111,右括号代价为−1-1−1): (1) 左括号个数等于右括号个数. (2) 括号的前缀和非 ...

  10. [ZJOI2010] 基站选址(线段树优化dp)

    problem luogu-P2605 solution 首先,肯定都能想到最暴力的 dpdpdp. dpi,j:idp_{i,j}:idpi,j​:i 个村庄为止一共选了 jjj 个基站,且第 ii ...

最新文章

  1. 机器学习隐私研究新进展:数据增强风险被低估,新算法“降服”维数依赖
  2. 表格布局(tablelayout)
  3. MySQL最后一次查询耗时查询
  4. python从多层循环嵌套中退出_python中退出多层循环的方法
  5. Django配置bootstrap
  6. [转]最常用的15大Eclipse开发快捷键技巧
  7. 每天看技术文章头大,搞点笑话轻松一下吧
  8. 你了解node多进程吗
  9. ASP.NETMVC Model验证(五)
  10. Spring MVC深入讲解
  11. Android Studio3.5 JAVA调用C++源码方法总结
  12. JS中clientHeight、scrollHeight、offsetHeight、scrollTop、offsetTop的定义
  13. 【机器学习】图像预处理
  14. AXURE版富文本输入框(富文本编辑器)教程+下载
  15. 视频演示 | 功能新增 | 增强版在线LEFSe分析和可视化鉴定标志性基因或物种
  16. activereport subreport
  17. showdown ( markdown解析)
  18. 夏普Sharp SF-S751D 一体机驱动
  19. Word:外国人中文译名中间的“点”怎么输入
  20. 腾讯云 wafer2 上手,轻松部署小程序后端!

热门文章

  1. 企业管理信息系统成功实施的四个阶段
  2. 我的 OCM 之路|书写无悔青春,追梦永不止步
  3. 鸿蒙OS开发蜂鸣器播放《两只老虎》
  4. 【win7安装composer错误】:The quot;https://getcomposer.org/download/1.6.2/composer.phar.sigquot; file cou
  5. php话费充值接口,手机话费充值接口
  6. 数据库与开源编译器框架LLVM
  7. 东北大学材料成型工艺学中期末复习
  8. Butterfly美化
  9. 数据库期末复习:选择题汇总
  10. Python UnboundLocalError: local variable ‘str‘ referenced before assignment