本着只贴代码不写分析的题解是在耍流氓的原则,还是决定写点分析。

思路很清晰,参考的官方题解,一下文字仅对题解做一个简要翻译。

题意:

有1~n这n个数,每个数用两次。构成一个长为2n的序列,而且要求序列满足先递增后递减(都是非严格的递增递减)。

再给出k个约束,每个约束形如1 >= 3这种,表示序列的第一个数要不小于第三个数。

问满足约束的合法序列有多少种。

分析:

首先先不考虑这些约束条件,考虑如何构造出这种序列。

考虑两个1放置的位置,因为序列是两边小中间大,所以这两个1要么放在前面两个位置,或者后面两个位置,要么一前一后,而且只有这三种放法。

事实上,不考虑约束条件的话,n个数能得到的合法的序列的个数为3n

因此这些数是1~n从两边往中间放的。

设d(L, R)表示[L, R]这个区间还没放数,满足约束条件的序列个数,则答案为d(1, 2n)

下面考虑如何处理这些不等式:

计算d(L, R)时,比如要放在L和L+1这两个格子,那么就考虑所有和L相关的不等式,以及和L+1相关的不等式。

为了更清楚起见,画一个图看看:

绿色表示已经放好数的区间,黄色表示正要放的两个格子,红色是还未放数的区间。

那么有大小关系:绿色的数 < 黄色的数 < 红色的数,两个黄色格子的数是相等的。

比如有不等式L >= v

如果a[L] == a[v],那么v应该等于L + 1,表示L和v两个位置放同一个数;

如果a[L] > a[v],那么v应该在绿色的区间表示之前已经放过数了,这样放在L的数才能比放在v的数大。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define MP make_pair
using namespace std; typedef long long LL; const int maxn = ; int n, k; vector<int> G[maxn], req[maxn]; LL d[maxn][maxn]; bool check(int L, int R, int l, int r)
{
for(int i = ; i < G[l].size(); i++)
{
int v = G[l][i], t = req[l][i];
if(t == -)
{
if(v < L || v > R || v == r) return false;
}
else if(t == -)
{
if(v < L || v > R) return false;
}
else if(!t)
{
if(v != r) return false;
}
else if(t == )
{
if(v >= L && v <= R && v != r) return false;
}
else
{
if(v >= L && v <= R) return false;
}
} for(int i = ; i < G[r].size(); i++)
{
int v = G[r][i], t = req[r][i];
if(t == -)
{
if(v < L || v > R || v == l) return false;
}
else if(t == -)
{
if(v < L || v > R) return false;
}
else if(!t)
{
if(v != l) return false;
}
else if(t == )
{
if(v >= L && v <= R && v != l) return false;
}
else
{
if(v >= L && v <= R) return false;
}
} return true;
} LL dp(int L, int R)
{
LL& ans = d[L][R];
if(ans >= ) return d[L][R];
if(L + == R)
{
if(check(L, R, L, R)) return 1LL;
return ;
} ans = ; if(check(L, R, L, L + ))
ans += dp(L + , R);
if(check(L, R, L, R))
ans += dp(L + , R - );
if(check(L, R, R - , R))
ans += dp(L, R - ); return ans;
} int main()
{
scanf("%d%d", &n, &k);
char eq[];
while(k--)
{
int u, v;
scanf("%d", &u);
scanf("%s", eq);
scanf("%d", &v); int t;
if(strcmp(eq, "<") == ) t = -;
else if(strcmp(eq, "<=") == ) t = -;
else if(strcmp(eq, "=") == ) t = ;
else if(strcmp(eq, ">=") == ) t = ;
else if(strcmp(eq, ">") == ) t = ;
else exit(); if(u == v)
{
if(abs(t) <= ) continue;
else { puts(""); exit(); }
} req[u].push_back(t); req[v].push_back(-t);
G[u].push_back(v); G[v].push_back(u);
} memset(d, -, sizeof(d)); printf("%I64d\n", dp(, n * )); return ;
}

代码君

CodeForces 567F DP Mausoleum的更多相关文章

  1. 【CodeForces 567F】Mausoleum

    寒假最后一题补完啦 ^∀^ 题意 1到n每个数字有两个,排成先不降后不升的序列,比如112332,并且满足k个形如 3 <= 6 代表第三个数字要≤第六个数字这样的约束要求,求有多少种排法. 分 ...

  2. Two Melodies CodeForces - 813D (DP,技巧)

    https://codeforces.com/problemset/problem/813/D dp[i][j] = 一条链以i结尾, 另一条链以j结尾的最大值 关键要保证转移时两条链不能相交 #in ...

  3. Consecutive Subsequence CodeForces - 977F(dp)

    Consecutive Subsequence CodeForces - 977F 题目大意:输出一序列中的最大的连续数列的长度和与其对应的下标(连续是指 7 8 9这样的数列) 解题思路: 状态:把 ...

  4. codeforces的dp专题

    1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个 ...

  5. Codeforces 721C [dp][拓扑排序]

    /* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG), ...

  6. CodeForces 607C (DP) Hard problem

    题目:这里 题意:给定n个字符串,每个字符串可以进行一项操作,就是将这个字符串交换,就是该字符串的第一个和最后一个交换,第二个和倒数第二个交换,以此类推,当然可以选择对于 该字符串进行或不进行这项操作 ...

  7. Codeforces 611d [DP][字符串]

    /* 题意:给一个长度不超过5000的字符串,每个字符都是0到9的数字. 要求将整个字符串划分成严格递增的几个数字,并且不允许前导零. 思路: 1.很开心得发现,当我在前i个区间以后再加一个区间的时候 ...

  8. Codeforces 404D [DP]

    /* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01 ...

  9. Codeforces 119C DP

    题意: 有n天,m门课和常数k; 每天上一门课,每门课程有两个属性,最少作业量a,最多作业量b,和难度c. 1<=a<=b<=1e16 c<=100 1<=n<=m ...

随机推荐

  1. postgresql 存储过程动态插入数据 2

    最近学习postgresql,正一个小活要用上,所以就开始学习了!然而,学习的过程极其艰辛,但却也充满了乐趣. 一般来说数据库的操作不外如何增,删,改,查,而首要的就是要添加数据到数据库中,因为以前的 ...

  2. gulp运行步骤

    一.运行→输入cmd→跳出命令窗口二.cd D: 敲回车进入D盘,cd www 进入项目路径 cd mygulp三.执行 cnpm install gulp --save-dev 命令 (初始化安装g ...

  3. web常见几种处理图标方法

    方法一: 用background制作小图标 像这样,拿到设计稿后把所有的图标放在一张图片上,利用background-position.width.height来控制图标的位置及大小. 代码: .ic ...

  4. Python+selenium之跳过测试和预期失败

    在运行测试时,需要直接跳过某些测试用例,或者当用例符合某个条件时跳过测试,又或者直接将测试用例设置为失败.unittest单元测试框架提供了实现这些需求的装饰器. 1.unittest.skip(re ...

  5. basic ,fundamental ,extreme ,utmost和radical.区别

    basic 普通用词,指明确.具体的基础或起点.fundamental 书面用词,不如basic使用广泛,侧重指作为基础.根本的抽象的事物.radical 着重指事物的根本或其来源.下面是extrem ...

  6. (四)SpringMVC之使用cookie实现记住密码的功能

    注意:因为实现记住密码的功能需要用到json,所以需要加上这条语句: <script type="text/javascript" src="scripts/jqu ...

  7. IT界程序员几大恶习能立即让你变穷,你有吗?

    IT软件开发,确实是各行业中薪水排名靠前的职业,月薪在八千以上的Java程序员多不胜数,但是不知有没有以下几种恶习?如果粘上一种,哪怕你薪水几万,估计最后也是囊中羞涩:综上所述列举以下几点,亲们自己对 ...

  8. 剑指offer55 字符流中第一个不重复的字符(最典型错误)

    典型并且基础的错误: class Solution { public: //Insert one char from stringstream void Insert(char ch) { ) res ...

  9. appium---AndroidSdk安装

    AndroidSDK指的是Android专属的软件开发工具包,被软件开发工程师用于为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合.Android又是采用java语言进行开发 ...

  10. 《队长说得队》【Alpha】Scrum meeting 1

    项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 ...