CodeForces 567F DP Mausoleum
本着只贴代码不写分析的题解是在耍流氓的原则,还是决定写点分析。
思路很清晰,参考的官方题解,一下文字仅对题解做一个简要翻译。
题意:
有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的更多相关文章
- 【CodeForces 567F】Mausoleum
寒假最后一题补完啦 ^∀^ 题意 1到n每个数字有两个,排成先不降后不升的序列,比如112332,并且满足k个形如 3 <= 6 代表第三个数字要≤第六个数字这样的约束要求,求有多少种排法. 分 ...
- Two Melodies CodeForces - 813D (DP,技巧)
https://codeforces.com/problemset/problem/813/D dp[i][j] = 一条链以i结尾, 另一条链以j结尾的最大值 关键要保证转移时两条链不能相交 #in ...
- Consecutive Subsequence CodeForces - 977F(dp)
Consecutive Subsequence CodeForces - 977F 题目大意:输出一序列中的最大的连续数列的长度和与其对应的下标(连续是指 7 8 9这样的数列) 解题思路: 状态:把 ...
- codeforces的dp专题
1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个 ...
- Codeforces 721C [dp][拓扑排序]
/* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG), ...
- CodeForces 607C (DP) Hard problem
题目:这里 题意:给定n个字符串,每个字符串可以进行一项操作,就是将这个字符串交换,就是该字符串的第一个和最后一个交换,第二个和倒数第二个交换,以此类推,当然可以选择对于 该字符串进行或不进行这项操作 ...
- Codeforces 611d [DP][字符串]
/* 题意:给一个长度不超过5000的字符串,每个字符都是0到9的数字. 要求将整个字符串划分成严格递增的几个数字,并且不允许前导零. 思路: 1.很开心得发现,当我在前i个区间以后再加一个区间的时候 ...
- Codeforces 404D [DP]
/* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01 ...
- Codeforces 119C DP
题意: 有n天,m门课和常数k; 每天上一门课,每门课程有两个属性,最少作业量a,最多作业量b,和难度c. 1<=a<=b<=1e16 c<=100 1<=n<=m ...
随机推荐
- JAVA基础之File类
个人理解: File是个文件类,可以用其增加.删除.查找某种类型的文件或者文件夹,同时根据其成员变量的特点可以综合利用,避免出现跨系统的时候出现错误,并且查找时最好输入绝对路径,以免出现不存在的文件. ...
- IO(转换流、缓冲流)
第1章 转换流 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者Output ...
- dubbo服务降级(1)
1. 在 dubbo 管理控制台配置服务降级 上图的配置含义是:consumer 调用 com.zhang.HelloService 的方法时,直接返回 null,不发起远程调用. 实际操作是:在 z ...
- VC中包含的头文件名不区分大小写
VC中包含的头文件名,不区分大小写如 #include "my.h" = #include "MY.H".
- Python使用easy-install安装时报UnicodeDecodeError的解决方法
Python使用easy-install安装时报UnicodeDecodeError的解决方法,有需要的朋友可以参考下. 问题描述: 在使用easy-install安装matplotlib.pypar ...
- hdu 3861 The King’s Problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- 不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧
Jerry和SAP成都研究院一些新同事聊天时,谈到ABAP和SAP GUI这个话题.很多新同事在加入SAP成都之前,是做Java和C++开发的,习惯了Eclipse/IntelliJ IDEA/Vis ...
- C#去掉字符串最后面的一个标点符号的写法
keywordHtml = keywordHtml.Remove(keywordHtml.LastIndexOf(','),1);
- Mysql command line
show databasename; use databasename; show tables; desc tablename;
- PAT (Basic Level) Practise (中文)- 1011. A+B和C (15)
http://www.patest.cn/contests/pat-b-practise/1011 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1 ...