numbers

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 196608/196608 K (Java/Others)
Total Submission(s): 154    Accepted Submission(s): 46

Problem Description
Now you have a stack and n numbers 1,2,3,…,n. These n numbers are pushed in the order and popped if the number is at the top of the stack. You can read the sample to get more details.
This question is quite easy. Therefore I must give you some limits.
There are m limits, each is expressed as a pair<A,B> means the number A must be popped before B.
Could you tell me the number of ways that are legal in these limits?
I know the answer may be so large, so you can just tell me the answer mod 1000000007(109+7).
Input
The first line contains an integer T(about 5),indicating the number of cases.
Each test case begins with two integers n(1≤n≤300) and m(1≤m≤90000).
Next m lines contains two integers A and B(1≤A≤n,1≤B≤n)
(P.S. there may be the same limits or contradict limits.)
Output
For each case, output an integer means the answer mod 1000000007.
Sample Input
5
1 0
5 0
3 2
1 2
2 3
3 2
2 1
2 3
3 3
1 2
2 3
3 1
Sample Output
1
42
1
2
0

Hint

The only legal pop-sequence of case 3 is 1,2,3.
The legal pop-sequences of case 4 are 2,3,1 and 2,1,3.

Source
题目大意:一个由1,2,......,n组成的排列,顺次插入栈中,你可以选择在任意时刻弹出栈顶元素,现在有m个要求,要求x必须在y之前出栈,问有多少种合法的出栈顺序.
分析:好题!
   先考虑没有要求的情况. 很显然就是卡特兰数. 可以用区间dp的方法去做:f[i][j] = Σf[i][k - 1] * f[k + 1][j],枚举的k是区间[i,j]中最后被弹出的元素,那么肯定先是区间[i,k-1]的元素被弹出,然后就是区间[k+1,j]的元素被弹出,最后是k被弹出.这是O(n^3)的做法
   如果有限制怎么办呢?能不能在原有的dp方案的基础上改进一下呢? 可以往两个方向思考,要么是给状态加上一维,要么是就沿用这个状态,把不满足限制的方案给排除掉. 加上一维是不现实的,因为复杂度已经达到了O(n^3),加上一维的话复杂度肯定会再上升一个级别.
   那就考虑如何把不满足限制的方案给排除掉.假设x必须要在y之前弹出,令x,y的较小值为min,较大值为max.对于x,y的限制,影响的只有包含x,y这两个点的区间,也就是区间左端点在[1,min],右端点在[max,n]的区间. 
   若x < y,那么x在排列中的位置肯定在y前面.前面说过元素弹出的顺序,如果k在x,y右边或者左边,那么作为一个子问题已经被解决了.如果k在x,y中间.只要k不是x,x永远比y先弹出. 那么对于被x,y影响的区间,一旦k = x,就不能统计进入答案中.
   若x > y,y在左边了.考虑k在y,x中间的情况.k 可以等于 y,这样y在x之后被弹出,但是一旦 y + 1 ≤ k ≤ x,则k是不合法的.
   预处理出不合法的状态是O(n^2m)的复杂度,显然是不可以接受的,怎么优化呢?
   k是要枚举的,但是区间的左右端点所在的区间是确定的,需要做的就是把这些区间快速打上标记.做法还是比较难想到的.
不合法的区间形如:[1,max],[1,max + 1],......,[1,n],[2,max],[2,max + 1],......,[min,n]. 对于二元组,一个处理方法是放到平面直角坐标系上,然后可以发现,这些点所形成的图形是一个矩形. 批量修改一个矩形,怎么快速改? 二维差分!怎么查询单个点的答案?前缀和!问题就这样被解决了.
   总复杂度O(n^3 + n*m).
   这道题综合了许多知识,把问题简化,得到一个做法后该如何推导出原问题的做法?能不能用上简化的问题的做法?如何快速修改左右端点所在区间都知道的所有区间?遇到二元组要怎么处理?如何快速修改一个矩形内所有点的值?如何查询单点答案?这就是这道题的思路.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const ll maxn = ,mod = 1e9+;
ll f[maxn][maxn];
int T,n,m,sum[maxn][maxn][maxn],a[maxn][maxn][maxn];
bool flag = true; struct node
{
int x,y;
} e[]; void add(int x3,int y3,int x4,int y4,int k)
{
sum[x3][y3][k]++;
sum[x4 + ][y4 + ][k]++;
sum[x4 + ][y3][k]--;
sum[x3][y4 + ][k]--;
} void pre()
{
for (int i = ; i <= m; i++)
{
ll x = e[i].x,y = e[i].y;
if (x < y)
add(,y,x,n,x);
else
{
for (int j = y + ; j <= x; j++)
add(,x,y,n,j);
}
}
for (int k = ; k <= n; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
sum[i][j][k] = sum[i - ][j][k] + sum[i][j - ][k] - sum[i - ][j - ][k] + sum[i][j][k];
} void solve()
{
for (int i = ; i <= n; i++)
{
f[i][i] = ;
f[i][i - ] = ;
}
f[n + ][n] = ;
for (int len = ; len <= n; len++)
for (int i = ; i + len - <= n; i++)
{
int j = i + len - ;
for (int k = i; k <= j; k++)
{
if (sum[i][j][k] == )
{
f[i][j] += f[i][k - ] * f[k + ][j] % mod;
f[i][j] %= mod;
}
}
}
} int main()
{
scanf("%d",&T);
while(T--)
{
memset(sum,,sizeof(sum));
memset(f,,sizeof(f));
flag = true;
scanf("%d%d",&n,&m);
for (ll i = ; i <= m; i++)
{
scanf("%d%d",&e[i].x,&e[i].y);
if (e[i].x == e[i].y)
flag = false;
}
if (!flag)
puts("");
else
{
pre();
solve();
printf("%lld\n",f[][n] % mod);
}
} return ;
}
   

Hdu5181 numbers的更多相关文章

  1. Java 位运算2-LeetCode 201 Bitwise AND of Numbers Range

    在Java位运算总结-leetcode题目博文中总结了Java提供的按位运算操作符,今天又碰到LeetCode中一道按位操作的题目 Given a range [m, n] where 0 <= ...

  2. POJ 2739. Sum of Consecutive Prime Numbers

    Sum of Consecutive Prime Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20050 ...

  3. [LeetCode] Add Two Numbers II 两个数字相加之二

    You are given two linked lists representing two non-negative numbers. The most significant digit com ...

  4. [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  5. [LeetCode] Count Numbers with Unique Digits 计算各位不相同的数字个数

    Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Examp ...

  6. [LeetCode] Bitwise AND of Numbers Range 数字范围位相与

    Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers ...

  7. [LeetCode] Valid Phone Numbers 验证电话号码

    Given a text file file.txt that contains list of phone numbers (one per line), write a one liner bas ...

  8. [LeetCode] Consecutive Numbers 连续的数字

    Write a SQL query to find all numbers that appear at least three times consecutively. +----+-----+ | ...

  9. [LeetCode] Compare Version Numbers 版本比较

    Compare two version numbers version1 and version1.If version1 > version2 return 1, if version1 &l ...

随机推荐

  1. java基础学习总结--开篇

    春去秋来,转眼间,参加工作快2年了.本来应该是3年,然在毕业的第一年,有试着从事过其他行业.最终结果是失败了.2016年又回来从事软件开发,转眼即将2年,在这期间有许多收获,当然也有彷徨迷茫的时候,人 ...

  2. KETTLE并行

    1.转换的并行 转换的并行是改变复制的数量 上面的转换相当于下面的: 实际是把一个任务拆成三部分执行,相当于在一个数据库连接中做了三次查询,数据库连接的开销没有增加,但是有三个进程一起执行. 2.jo ...

  3. 第八次作业(课堂实战)- 项目UML设计

    本次作业博客 团队信息 队名:起床一起肝活队 原组长: 白晨曦(101) 原组员: 李麒 (123) 陈德斌(104) 何裕捷(214) 黄培鑫(217) 王焕仁(233) 林志华(128) 乐忠豪( ...

  4. Java多线程中的wait与notify

    一.wait: 1. wait 是 object 类的方法, sleep 是 thread 类的方法. 2. 当前的正在我这个对象访问的线程 wait. 3. 当前的这个线程, 锁定在当前对象的这个线 ...

  5. QMdiArea及QMdiSubWindow实现父子窗口及布局方法

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QMdiArea及QMdiSubWindow实现父子窗口及布局方法     本文地址:http ...

  6. 【beta】nice!-------约吧NABCD

    小组名称:nice! 组长:李权 成员:于淼  刘芳芳韩媛媛 宫丽君 项目内容:约跑app(约吧) 约吧APP下载地址: 百度云:链接:http://pan.baidu.com/s/1jHNBR3g ...

  7. python基础(一)简单入门

    一.第一个python程序 1.交互式编程 直接在命令行里面输入python即可进入python交互式命令行,linux下一样: 在 python 提示符中输入以下文本信息,然后按 Enter 键查看 ...

  8. oracle 行转列和列转行

    WITH L AS ( ), m AS ( SELECT A.LV AS LV_A, B.LV AS LV_B, TO_CHAR(B.LV) || 'x' || TO_CHAR(A.LV) || '= ...

  9. 【Linux 命令】- tar 命令

    语法 tar [-ABcdgGhiklmMoOpPrRsStuUvwWxzZ][-b <区块数目>][-C <目的目录>][-f <备份文件>][-F <Sc ...

  10. webgl helloworld

    之前的webgl 初识1, 初识2 已经介绍了webgl的基本概念,工作原理. 没有理解的自己yy. 现呈上例子一枚 <!DOCTYPE html> <html lang=" ...