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 ...
随机推荐
- NIO基础之Buffer
java.io 核心概念是流,即面向流的编程,在java中一个流只能是输入流或者输出流,不能同时具有两个概念. java.nio核心是 selector.Channel.Buffer ,是面向缓冲区( ...
- jstl表达式的应用的条件
在el表达式中,有时我们要写for循环,这时我们要写 <c:forEach items="${list}" var="news" > </c: ...
- mitmproxy抓包软件在mac上边的安装
官网介绍:mitmproxy is a free and open source interactive HTTPS proxy. mitmproxy 是用 Python 和 C 开发的一个中间人代理 ...
- java 实现 excel sheet 拷贝到另一个Excel文件中 poi
public class CopyExcelSheetToAnotherExcelSheet { public static void main(String[] args) throws FileN ...
- 用户登录保存数据实例(慕课笔记 使用SharedPreferences保存用户名)
学习视频之后自己操作时的笔记. 0.视频地址:http://www.imooc.com/video/3265 1.功能预览: 说明:1)输入错误用户名和密码,点击登录,弹出提示框“禁止登录”: 2)输 ...
- SharePoint 2016 功能比较
SharePoint 2016中有很多功能.我们经常和客户谈论SharePoint安装时,我问他们是否计划安装SharePoint Server 2016 Standard或Enterprise.通常 ...
- LR脚本示例之常用函数
1.变量和参数的设置 //将IP地址和端口放入到参数中lr_save_string("127.0.0.1:1080","ip"); //退出脚本建议使用lr_e ...
- GetOpenFileName 选择文件夹的解决方法
某些环境下(如WIN PE)windows自带的选择文件夹api不能使用或者体验不佳.现在利用GetOpenFileName的回掉参数实现了选择文件夹选择功能. #include <Window ...
- 如何在程序中加入Growl通知
Growl for Windows – Mac 样式的信息提示工具.目前已经支持的软件包括:Outlook,Visual Studio 等以及一个利用命令行从本地或者远程发送消息过来的工具 .Grow ...
- 使用Python-OpenCV向图片添加噪声(高斯噪声、椒盐噪声)
在matlab中,存在执行直接得函数来添加高斯噪声和椒盐噪声.Python-OpenCV中虽然不存在直接得函数,但是很容易使用相关的函数来实现. 代码: import numpy as np impo ...