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 ...
随机推荐
- Servlet之sendRedirect和getRequestDispatch
Servlet的请求重定向和请求转发方法的比较分析: 1.getRequestDispatch是属于httpServletRequest对象的方法,请求转发是在同一个请求中完成的,因此整个过程只包含一 ...
- Object类-try-catch-finally-throw-throws-自定义异常
一.Object类 Object类是最顶端的类,其它类都是它的子类,它的方法可以被继承.如果定义的类没有继承别的类,那它的直接父类就是Object.如果方法参数类型为object类型, 则调用 ...
- 洛谷 P1345 [USACO5.4]奶牛的电信Telecowmunication
题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...
- 使Win10用户获得特殊权限以便删除相应文件(夹)
依次访问: 本地用户和组(右击“此电脑”): 用户: 右击:当前用户名: 属性: 添加: 输入:System Managed Accounts Group: 检查名称(可选): 确定: 重启电脑. 参 ...
- WebClient UI和Tomcat的启动器
WebClient UI 我们在WebClient UI的开发工具里点了Test按钮, 会在浏览器以测试模式打开选中的view.这背后发生了什么事?注意浏览器地址栏的bspwd_cmp_test,这是 ...
- linux基本命令及使用方法
shell环境: shell:命令解释器,是Linux 系统的用户界面,提供了用户与内核进行交互操作的一种接口,它接收用户输入的命令并把它送入内核去执行. bash:是GNU 计划中重要的工具软件之一 ...
- ovx openVirtex安装
搞了好久的pox实验,中途一个星期没更新了吧, 今天继续... 新手第一次搞还是在虚拟机上最安全~ ovx参照上面的做吧,注意必须在联网的情况下,否则很多控件都连不上(第一次做的时候虚拟机没配ip 坑 ...
- jquery的正则表达式
正则表达式 位置: ^ 开头 $ 结尾 次数: * 0或多个 + 1或多个 ? 0或1个 {n} 就是n个 {n,} 至少n个 {n,m} ...
- MFC里 显示设备上下文CClient dc(this) 和 CPaintDC dc(this)
1 CPaintDC类(1)CPaintDC类是CDC类的一个派生类,该类一般用在响应WM_PAINT消息的函数OnPaint()中.(2)WM_PAINT消息是当窗口的某个区域需要重画时激发的窗口消 ...
- NOIP2013 乌龟棋
描述 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点 ...