【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp
题目描述
Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a variant of the game for themselves to play. Being played by clumsy animals weighing nearly a ton, Cow Hopscotch almost always ends in disaster, but this has surprisingly not deterred the cows from attempting to play nearly every afternoon.
The game is played on an R by C grid (2 <= R <= 750, 2 <= C <= 750), where each square is labeled with an integer in the range 1..K (1 <= K <= R*C). Cows start in the top-left square and move to the bottom-right square by a sequence of jumps, where a jump is valid if and only if
1) You are jumping to a square labeled with a different integer than your current square,
2) The square that you are jumping to is at least one row below the current square that you are on, and
3) The square that you are jumping to is at least one column to the right of the current square that you are on.
Please help the cows compute the number of different possible sequences of valid jumps that will take them from the top-left square to the bottom-right square.
输入
输出
Output the number of different ways one can jump from the top-left square to the bottom-right square, mod 1000000007.
样例输入
4 4 4
1 1 1 1
1 3 2 1
1 2 4 1
1 1 1 1
样例输出
5
题解
动态开点线段树优化dp
首先有dp方程$f[x][y]=\sum\limits_{i=1}^{x-1}\sum\limits_{j=1\& c[i][j]\neq c[x][y]}^{y-1}f[i][j]=\sum\limits_{i=1}^{x-1}\sum\limits_{j=1}^{y-1}f[i][j]-\sum\limits_{i=1}^{x-1}\sum\limits_{j=1\& c[i][j]=c[x][y]}^{y-1}f[i][j]$。
前面那个东西我们可以使用二维前缀和优化,而后面的那个东西只能使用数据结构。
考虑我们的dp方式:先循环行、再循环列。那么搜到某一行时,它之前的一定是行数比它小的,所以不用管这个条件,只要维护列即可,即维护第1~x列某种颜色的f之和。
由于颜色数太多,显然不能使用静态数据结构,所以使用动态开点线段树,对每一个颜色开一棵线段树维护区间和。
对于第i行,先对于第j列求出1~j-1列与它颜色相同的f的和,然后再循环一遍,更新二维前缀和及线段树。
时间复杂度$O(nm\log nm)$
#include <cstdio>
#include <algorithm>
#define N 800
#define M 600000
using namespace std;
const int mod = 1000000007;
int c[N][N] , f[N][N] , sum[N][N] , root[M] , ls[M * 15] , rs[M * 15] , si[M * 15] , tot;
void update(int p , int a , int l , int r , int &x)
{
if(!x) x = ++tot;
si[x] = (si[x] + a) % mod;
if(l == r) return;
int mid = (l + r) >> 1;
if(p <= mid) update(p , a , l , mid , ls[x]);
else update(p , a , mid + 1 , r , rs[x]);
}
int query(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return si[x];
int mid = (l + r) >> 1 , ans = 0;
if(b <= mid) ans += query(b , e , l , mid , ls[x]);
if(e > mid) ans += query(b , e , mid + 1 , r , rs[x]);
return ans % mod;
}
int main()
{
int n , m , i , j;
scanf("%d%d%*d" , &n , &m);
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= m ; j ++ )
scanf("%d" , &c[i][j]);
f[1][1] = sum[1][1] = 1 , update(1 , 1 , 1 , m , root[c[1][1]]);
for(i = 2 ; i <= n ; i ++ ) sum[i][1] = 1;
for(i = 2 ; i <= m ; i ++ ) sum[1][i] = 1;
for(i = 2 ; i <= n ; i ++ )
{
for(j = 2 ; j <= m ; j ++ ) f[i][j] = (sum[i - 1][j - 1] - query(1 , j - 1 , 1 , m , root[c[i][j]]) + mod) % mod;
for(j = 2 ; j <= m ; j ++ ) sum[i][j] = (((sum[i][j - 1] + sum[i - 1][j]) % mod + f[i][j]) % mod - sum[i - 1][j - 1] + mod) % mod;
for(j = 2 ; j <= m ; j ++ ) update(j , f[i][j] , 1 , m , root[c[i][j]]);
}
printf("%d\n" , f[n][m]);
return 0;
}
【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp的更多相关文章
- BZOJ3939 : [Usaco2015 Feb]Cow Hopscotch
设f[i][j]表示到(i,j)的方案数,则有 $f[i][j]=\sum f[x][y](x<i,y<j,a[x][y]!=a[i][j])=\sum f[x][y](x<i,y& ...
- 【BZOJ3939】[Usaco2015 Feb]Cow Hopscotch 动态规划+线段树
[BZOJ3939][Usaco2015 Feb]Cow Hopscotch Description Just like humans enjoy playing the game of Hopsco ...
- [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)
题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...
- 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化
4636: 蒟蒻的数列 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 247 Solved: 113[Submit][Status][Discuss ...
- codeforces 893F - Physical Education Lessons 动态开点线段树合并
https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...
- codeforces 915E - Physical Education Lessons 动态开点线段树
题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...
- CF915E Physical Education Lessons 动态开点线段树
题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
随机推荐
- BZOJ 2654: tree Kruskal+二分答案
2654: tree Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1863 Solved: 736[Submit][Status][Discuss ...
- 2017-3-7-lint82single-number
2017-3-7-lint82single-number 在河之洲 算法 小书匠 problem 82single-number/ solution int singleNumber(vector&l ...
- 任务管理器 用 Ctrl + Shift + Esc 替换 Ctrl + Alt + Del
任务管理器 用 Ctrl + Shift + Esc 替换 Ctrl + Alt + Del
- oracle 数据导到 sql server
方法一: navicate:用法比较简单,选择工具-数据传输就可以了.目前测试了下暂时没遇到什么问题. 方法二: Microsoft SQL Server Migration Assistant 8. ...
- Bootstrap历练实例:堆叠的进度条
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- Dede技巧
解决DEDE图集上传图片时跳出302错误 本地上传图集的时候突然提示网页出错,还爆出302错误. 解决办法是在include/userlogin.class.php文件中的第二行session_s ...
- linux简单常用命令
除了yum命令,还有些简单的命令,在此记录一下,加深记忆: free -h 查询内存和交换分区. rpm -qa | grep libaio 查看当前环境是否安装某rpm软件包
- 【Git版本控制】Git的merge合并分支命令
1.实例 git checkout master git merge dev merge合并分支只对当前分支master产生影响,被合并的分支dev不受影响. 假设你有两个分支,“stable” 和 ...
- python--以1-31的数字作为结尾的列表?论英文好的重要性!
一.python基础教程第2板(修订版)[代码清单2-1]中有一段要求打印‘以1-31的数字作为结尾的列表’ 截取代码示例:endings =['st','nd','rd'] +17*['th'] + ...
- 如何下载并安装 robomongo 到Ubuntu 系统
官网下载软件,https://robomongo.org/download wget https://download.robomongo.org/1.2.1/linux/robo3t-1.2.1-l ...