当前位置:网站首页>2022杭电多校第三场 Two Permutations (dp, 哈希)
2022杭电多校第三场 Two Permutations (dp, 哈希)
2022-07-29 23:51:00 【jangyi.】
1012 Two Permutations
题意:
给定两个 1 − n 1 - n 1−n的全排列数组 P , Q P,Q P,Q。一个空排列 R R R,每次可以从两个排列的首位数字选一个插到 R R R的后面,然后该数字从排列中删除,最后可以 R R R是一个长度为 2 n 2n 2n的数组。问:给定最终的 R R R,有多少种方案可以构成。
思路:
考虑一个排列 P P P的放置方案。显然, 1 − n 1-n 1−n中每个数字会出现两次,我们记录每个数字 p [ i ] p[i] p[i]出现在 R R R数组中的位置为 p o s [ p [ i ] ] [ 0 ] , p o s [ p [ i ] ] [ 1 ] pos[p[i]][0],pos[p[i]][1] pos[p[i]][0],pos[p[i]][1]。考虑动态规划: d p [ i ] [ j ] dp[i][j] dp[i][j]表示数字 P [ i ] P[i] P[i]匹配 p [ i ] p[i] p[i]在 R R R中第 j j j次出现的位置的方案数。然后我们可以枚举 p [ i + 1 ] p[i+1] p[i+1]出现的位置,那么在这两个位置中间就是由 Q Q Q中连续的一段子串所放置,那么我们可以预处理哈希然后 O ( 1 ) O(1) O(1)判断 Q Q Q中连续的一段是否完全匹配 R R R的一段子串。
code:
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> pii;
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') {
if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N = 3e5 + 10, M = N * 2, mod1 = 998244353, mod2 = 1e9 + 7;
inline LL ksm(LL a, LL b, int mod){
LL ans = 1;
for(; b; b >>= 1, a = a * a % mod) if(b & 1) ans = ans * a % mod;
return ans;
}
int dx[] = {
1, -1, 0, 0};
int dy[] = {
0, 0, -1, 1};
//----------------------------------------------------------------------------------------//
ULL fb[N], fc[N << 1], p[N << 1];
int n, a[N], b[N], c[N << 1];
int dp[N][2], pos[N][2];
inline ULL get(ULL f[], int l, int r) {
return f[r] - f[l - 1] * p[r - l + 1];
}
inline bool check(int lb, int rb, int lc, int rc) {
if(lb > rb) return 1;
if(lb < 1 || rb > n || lc < 1 || rc > n + n) return 0;
return get(fb, lb, rb) == get(fc, lc, rc);
}
inline void up(int &x, int y) {
x = x + y >= mod1 ? x + y - mod1 : x + y;
}
void solve() {
read(n);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= n; i++) read(b[i]);
for(int i = 1; i <= n + n; i++) read(c[i]);
for(int i = 1; i <= n; i++) for(int j = 0; j < 2; j++) dp[i][j] = 0;
for(int i = 1; i <= n; i++) pos[i][0] = pos[i][1] = 0;
for(int i = 1; i <= n; i++) fb[i] = fb[i - 1] * 233 + b[i];
for(int i = 1; i <= n << 1; i++) fc[i] = fc[i - 1] * 233 + c[i];
for(int i = 1; i <= n << 1; i++) {
if(!pos[c[i]][0]) pos[c[i]][0] = i;
else pos[c[i]][1] = i;
}
int Q = 1;
for(; Q <= n; Q++) if(!pos[Q][0] || !pos[Q][1]) break;
if(Q != n + 1) {
puts("0");
return;
}
for(int j = 0; j < 2; j++) {
int x = pos[a[1]][j];
if(check(1, x - 1, 1, x - 1)) dp[1][j] = 1;
}
for(int i = 1; i < n; i++) {
for(int j = 0; j < 2; j++) {
if(dp[i][j]) {
int x = pos[a[i]][j];
for(int k = 0; k < 2; k++) {
int y = pos[a[i + 1]][k];
if(y <= x) continue;
if(check(x - i + 1, y - i - 1, x + 1, y - 1))
up(dp[i + 1][k], dp[i][j]);
}
}
}
}
int ans = 0;
for(int j = 0; j < 2; j++)
if(dp[n][j]) {
int x = pos[a[n]][j];
if(check(x - n + 1, n, x + 1, n + n )) up(ans, dp[n][j]);
}
printf("%d\n", ans);
}
signed main() {
#ifdef JANGYI
freopen("input.in", "r", stdin);
freopen("out.out", "w", stdout);
auto now = clock();
#endif
// ios::sync_with_stdio(false);
// cin.tie(0);
p[0] = 1;
for(int i = 1; i < N << 1; i++) p[i] = p[i - 1] * 233;
int T = 1;
read(T);
while(T--) {
solve();
}
#ifdef JANGYI
cout << "================================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}
边栏推荐
- MySQL 用 BETWEEN AND 日期查询包含范围边界
- 重写并自定义依赖的原生的Bean方法
- 读书笔记:《这才是心理学:看穿伪心理学的本质(第10版)》
- 2022年企业直播行业发展洞察
- Docker install MySQL8.0
- The go language (functions, closures, defer, panic/recover, recursion, structure, json serialization and deserialization)
- C陷阱与缺陷 第4章 链接 4.1 什么是链接器
- C陷阱与缺陷 第3章 语义“陷阱” 3.10 为函数main提供返回值
- 一文看懂拉格朗日乘子法、KKT条件和对偶问题
- rk-boot框架实战(1)
猜你喜欢

学会使用MySQL的Explain执行计划,SQL性能调优从此不再困难

决策树原理及代码实现

Design for failure 12 common design ideas

BEVDetNet:Bird‘s Eye View LiDAR Point Cloud based Real-time 3D Object Detection for Autonomous Drivi

mysql使用on duplicate key update批量更新数据

devops学习(八) 搭建镜像仓库---jenkins推送镜像

vim相关介绍(二)

能源企业数字化转型背景下的数据安全治理实践路径

经典论文-SqueezeNet论文及实践

微信小程序获取手机号getPhoneNumber接口报错41001
随机推荐
经典论文-SqueezeNet论文及实践
Go language serialization and deserialization and how to change the uppercase of the json key value to lowercase if the json after serialization is empty
c语言小游戏扫雷
First Normal Form, Second Normal Form, Third Normal Form
UE4 makes crosshair + recoil
go语言(函数、闭包、defer、panic/recover,递归,结构体,json序列化与反序列化)
「大厂必备」系列之Redis主从、持久化、哨兵
种类并查集(反集),学习T宝代码
devops学习(九) Helm工具--持续部署
Add, delete, modify and query the database
How to design and implement report collaboration system for instruction set data products——Development practice of industrial collaborative manufacturing project based on instruction set IoT operating
月薪15k的阿里测试岗,面试原来这么简单
微信小程序获取手机号getPhoneNumber接口报错41001
USACO2008通信线路
Mysql8.0新特性之详细版本
图像的IO操作
leetcode122. Best Time to Buy and Sell Stock II 买卖股票的最佳时机 II(简单)
vim相关介绍(二)
EA&UML日拱一卒-多任务编程超入门-(8)多任务安全的数据类
Redis系列:高可用之Sentinel(哨兵模式)