题目描述

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.

就像人类喜欢跳格子游戏一样,FJ的奶牛们发明了一种新的跳格子游戏。虽然这种接近一吨的笨拙的动物玩跳格子游戏几乎总是不愉快地结束,但是这并没有阻止奶牛们在每天下午参加跳格子游戏 
游戏在一个R*C的网格上进行,每个格子有一个取值在1-k之间的整数标号,奶牛开始在左上角的格子,目的是通过若干次跳跃后到达右下角的格子,当且仅当格子A和格子B满足如下条件时能从格子A跳到格子B: 
1.B格子在A格子的严格右方(B的列号严格大于A的列号) 
2.B格子在A格子的严格下方(B的行号严格大于A的行号) 
3.B格子的标号和A格子的标号不同 
请你帮助奶牛计算出从左上角的格子到右下角的格子一共有多少种不同的方案

输入

The first line contains the integers R, C, and K. The next R lines will each contain C integers, each in the range 1..K.
第一行包含两个整数R C K 
接下来的R行,每行C个整数表示格子的标号

输出

Output the number of different ways one can jump from the top-left square to the bottom-right square, mod 1000000007.

一行,代表有多少种不同的方案,由于答案很大,请输出答案对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的更多相关文章

  1. 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& ...

  2. 【BZOJ3939】[Usaco2015 Feb]Cow Hopscotch 动态规划+线段树

    [BZOJ3939][Usaco2015 Feb]Cow Hopscotch Description Just like humans enjoy playing the game of Hopsco ...

  3. [2016湖南长沙培训Day4][前鬼后鬼的守护 chen] (动态开点线段树+中位数 or 动规 or 贪心+堆优化)

    题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...

  4. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  5. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  6. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

  7. codeforces 915E - Physical Education Lessons 动态开点线段树

    题意: 最大$10^9$的区间, $3*10^5$次区间修改,每次操作后求整个区间的和 题解: 裸的动态开点线段树,计算清楚数据范围是关键... 经过尝试 $2*10^7$会$MLE$ $10^7$会 ...

  8. CF915E Physical Education Lessons 动态开点线段树

    题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...

  9. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

随机推荐

  1. 【TensorFlow入门完全指南】神经网络篇·MLP多层感知机

    前面的不做过多解释了. 这里定义了两个占位符,各位也知道,在训练时,feed_dict会填充它们. 定义相关网络. 这里是权值矩阵和偏差. 这里是实例化了网络,定义了优化器和损失,和上一篇一样. 最后 ...

  2. 爬虫3_python2

    # coding=utf-8 import urllib params=urllib.urlencode({'t':1,'eggs':2,'bacon':0})#现在大多数网站都是动态网页,需要你动态 ...

  3. JavaScript实用的例子

    ---恢复内容开始--- 1.发送验证码 <input id="send" type="button" value="发送验证码"&g ...

  4. Python——函数入门(二)

    一.函数的参数 我们在定义函数时,可以定义形式参数(简称形参),这些形参的值在函数调用的时候才会确定,形参的值由调用者负责传入. 1.关键字参数 在Python中,函数的参数名并不是没有意义的,在调用 ...

  5. 解决vs 编译的bug“请检查是否是磁盘空间不足、路径无效或权限不够”

    昨晚用vs编译遇到一个问题,编译一半发现硬盘没空间,一直重启vs,重启电脑, 删除pdb文件都没用,之后尝试重新生成解决方案,就解决了.这个是vs的一个bug

  6. ios sinaweibo 客户端(一)

    上一篇sina微博Demo已经完成的认证,下面就开始进入微博相关内容的加载及显示.其实主要的工作就是调用微博API 加载相关的json数据,然后进行解析,然后在界面中进行组织好在tableview中进 ...

  7. Bzoj 近期题目一句话题解

    目录 Bzoj 近期题目题解 1000: A+B Problem (模拟) 1008: [HNOI2008]越狱 (容斥) 1012: [JSOI2008]最大数maxnumber (线段树) 103 ...

  8. [LUOGU] P4251 [SCOI2015]小凸玩矩阵

    行列看成点,格子看成边,二分一个边权,删去大于它的边,新图上的最大流>k则答案可以更优,小于k则调整左边界. #include<algorithm> #include<iost ...

  9. 标准C++(3)重载

    一.函数的重载 c++中同一作用域下能够定义同名的函数(这就叫重载),但必须满足如下要求: 1.函数的参数列表必须不同,可以使参数数量不同,也可以使参数的类型不同,甚至是参数的顺序不同. 2.函数的返 ...

  10. 怎么删除服务中的mysql服务

    可以进WINDOWS的管理里查看MYSQL的服务,把它停止或以DOS下用命令停止1.如果要卸载MYSQL执行下面命令:DOS下>mysqld -remove mysql2.启动MYSQL: DO ...