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. 《零基础学HTML5+CSS3(全彩版)》读书笔记

    2019年1月31日星期四 1点 <零基础学HTML5+CSS3(全彩版)>开始全面学习 前提: 11月20日开始学Python,可能因为太累了,也可能遇到了瓶颈,进入了一个迷茫期,1月6 ...

  2. 常用monkey_app稳定性

    Monkey稳定性测试 1       前言 为方便快速上手Monkey测试相关问题,针对测试中发现的Monkey问题进行了整理总结,供定位Monkey参考. 2       关于Monkey测试 2 ...

  3. Java接口获取系统配置信息

    Java获取当前运行系统的配置信息 接口:System.getProperty() 参数 描述 java.version Java运行时环境版本 java.vendor Java运行时环境供应商 ja ...

  4. Linux内核学习笔记(3)-- 进程的创建和终结

    一. 进程创建: Unix 下的进程创建很特别,与许多其他操作系统不同,它分两步操作来创建和执行进程: fork() 和 exec() .首先,fork() 通过拷贝当前进程创建一个子进程:然后,ex ...

  5. scrapy-redis+selenium+webdriver 部署到linux上

    背景:在使用selenium时,在本地使用windows,都会有一个图形界面,但是到了生产环境linux上没有了图形界面怎么部署呢? 解决方案: 1.安装图形化界面,不推荐,因为安装图形化界面会占用很 ...

  6. mysql常用语句入门整理

    这篇属于小白入门级别,如果你已经高手可以直接跳过 1.运行数据库mysqld.exe,客户端直接mysql -uroot(root是默认用户名) -p 2 showdatabases,showtabl ...

  7. USACO 2.4.4 Bessie Come Home 回家(最短路)

    Description 现在是晚餐时间,而母牛们在外面分散的牧场中. 农民约翰按响了电铃,所以她们开始向谷仓走去. 你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只速度最快 ...

  8. 咱们的team1序章

    之前都参加了好多组织,这是第一次参加变成组织.首先要介绍团队名称了,为什么叫“咱们的team”呢,因为,我们需要每个人都认真的参与进来,只有每个人都十分投入地参与进来,这个team才能称之为一个tea ...

  9. 第11章 认识和学习bash

    认识bash这个shell 硬件.内核和shell 用户操作计算机流程如下: 用户——>用户界面(shell,KDE,application)——>核心(kernel)——>硬件(h ...

  10. LAMP环境搭建Wordpress个人博客

    LAMP简要介绍 L:LinuxA:Apache(httpd)M:MySQL , MariadbP:php, perl , python 静态资源:图片,文档,视频,HTML代码,CSS代码,js代码 ...