[2021 CSP-S提高组] 题解(廊桥分配+括号序列+回文+交通规划)

2021 CSP-S 题解

  • 廊桥分配
  • 括号序列
  • 回文
  • 交通规划

配合👉CSP-S游记 食用更佳哦~

【雷】:只是在民间数据过了,不保证一定正确。仅供参考!!!
【雷】:只是在民间数据过了,不保证一定正确。仅供参考!!!
【雷】:只是在民间数据过了,不保证一定正确。仅供参考!!!

廊桥分配

problem

题目链接


solution

显然暴力就是枚举国内的廊桥数量,然后模拟一遍,O(n2)O(n^2)O(n2)

正解就是加速这个过程。

f1[i]:f_1[i]:f1[i]: 国内有 iii 个廊桥能承载的飞机数量,fi[i]:f_i[i]:fi[i]: 国外的。

最后就是 max⁡{f1[i]+f2[n−i]}\max\Big\{f_1[i]+f_2[n-i]\Big\}max{f1[i]+f2[ni]}

考虑将 nnn 个廊桥看成 nnn 个桶,对于国内飞机,尽量地往前停,否则就再开一个廊桥停这个飞机,用前缀和就能求得 f1[i]/f2[i]f_1[i]/f_2[i]f1[i]/f2[i]

可以通过 set\text{set}set 维护,迅速找到每架飞机着陆前空的廊桥。


code

#include <set>
#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 100005
set < pair < int, int > > s;
int f1[maxn], f2[maxn];
int n, m1, m2;void calc( int m, int *f ) {s.clear();for( int i = 1, x, y;i <= m;i ++ ) {scanf( "%d %d", &x, &y );s.insert( { x, y } );}for( int i = 1;i <= m;i ++ ) {auto it = s.begin();while( it != s.end() ) {f[i] ++;int k = it -> second;s.erase( it );it = s.lower_bound( { k + 1, 0 } );}f[i] += f[i - 1];}
}int main() {scanf( "%d %d %d", &n, &m1, &m2 );calc( m1, f1 );calc( m2, f2 );int ans = 0;for( int i = 0;i <= n;i ++ )ans = max( ans, f1[i] + f2[n - i] );printf( "%d\n", ans );return 0;
}

括号序列

problem

题目链接


solution

这道题难就难在 **()** 是不合法的。

为了知道左右的信息,我们选择区间 dpdpdp

g[l,r]:[l,r]g[l,r]:[l,r]g[l,r]:[l,r] 能否全为 ∗*

f[l,r]:[l,r]f[l,r]:[l,r]f[l,r]:[l,r] 强制 l−rl-rlr 括号匹配的方案数

dp[l,r]:[l,r]dp[l,r]:[l,r]dp[l,r]:[l,r] 为超级完美序列的方案数,不要求 l−rl-rlr 一定匹配

转移很简单,就是将合法的规则翻译成方程式即可。

  • (***(...)) 枚举左边连续一段 ∗*
  • ((...)***) 枚举右边连续一段 ∗*
  • ((...)) 直接嵌套一个匹配括号对
  • ()**() l−rl-rlr 与不同的括号匹配,中间要么为 ∅\empty 要么为连续的 ∗*

主要是 dp−fdp-fdpf 之间相互转移,ggg 是预处理做的。

这就是妥妥的 O(n4)O(n^4)O(n4) 的转移。

正解就是在这个基础上进行了前缀和/后缀和的优化。


code-65’

#include <cstdio>
#define maxn 505
#define int long long
#define mod 1000000007
int n, m;
char s[maxn];
int f[maxn][maxn], dp[maxn][maxn];
bool g[maxn][maxn];signed main() {scanf( "%lld %lld %s", &n, &m, s + 1 );for( int i = 1;i <= n;i ++ ) {if( s[i] == '*' or s[i] == '?' ) g[i][i] = 1;g[i][i - 1] = 1;}for( int len = 2;len <= m;len ++ )for( int i = 1;i + len - 1 <= n;i ++ ) {int j = i + len - 1;if( s[i] == '*' or s[i] == '?' ) g[i][j] |= g[i + 1][j];if( s[j] == '*' or s[j] == '?' ) g[i][j] |= g[i][j - 1];}for( int i = 1;i < n;i ++ )if( s[i] == ')' or s[i] == '*' or s[i + 1] == '(' or s[i + 1] == '*' ) continue;else f[i][i + 1] = dp[i][i + 1] = 1;for( int len = 3;len <= n;len ++ ) for( int i = 1;i + len - 1 <= n;i ++ ) {int j = i + len - 1;if( s[i] == ')' or s[i] == '*' or s[j] == '(' or s[j] == '*' ) continue;f[i][j] = ( f[i][j] + dp[i + 1][j - 1] ) % mod;if( j - 1 - ( i + 1 ) + 1 <= m ) f[i][j] = ( f[i][j] + g[i + 1][j - 1] ) % mod;for( int k = i + 2;k < j - 1;k ++ ) if( k - 1 - ( i + 1 ) + 1 > m ) break;else f[i][j] = ( f[i][j] + g[i + 1][k - 1] * dp[k][j - 1] ) % mod;for( int k = j - 2;k > i + 1;k -- )if( ( j - 1 ) - ( k + 1 ) + 1 > m ) break;else f[i][j] = ( f[i][j] + g[k + 1][j - 1] * dp[i + 1][k] ) % mod;for( int k = i + 1;k < j - 1;k ++ ) for( int t = 0;t <= m;t ++ )if( k + t + 1 >= j ) break;else dp[i][j] = ( dp[i][j] + f[i][k] * dp[k + t + 1][j] * g[k + 1][k + t] ) % mod;dp[i][j] = ( dp[i][j] + f[i][j] ) % mod;}printf( "%lld\n", dp[1][n] );return 0;
}

code-100‘

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define mod 1000000007
#define maxn 505
int f[maxn][maxn], g[maxn][maxn], h[maxn][maxn];
char s[maxn];
int n, m;bool is( int x, char c ) {if( x < 1 or x > n ) return 0;else return s[x] == '?' or s[x] == c;
}signed main() {scanf( "%lld %lld %s", &n, &m, s + 1 );for( int i = 2;i <= n;i ++ ) f[i][i - 1] = 1;for( int l = n;l;l -- )for( int r = l;r <= n;r ++ ) {if( is( l, '(' ) and is( r, ')' ) ) {f[l][r] = f[l + 1][r - 1];for( int i = l + 2;i <= min( l + m + 1, r ) and is( i - 1, '*' );i ++ )f[l][r] = ( f[l][r] + f[i][r - 1] ) % mod;for( int i = r - 2;i >= max( l + 1, r - m - 1 ) and is( i + 1, '*' );i -- )f[l][r] = ( f[l][r] + f[l + 1][i] ) % mod;}h[l][r] = g[l][r] = f[l][r];for( int i = r - 1;i >= r - m and is( i + 1, '*' );i -- ) g[l][r] = ( g[l][r] + h[l][i] ) % mod;for( int i = l;i < r;i ++ ) f[l][r] = ( f[l][r] + g[l][i] * f[i + 1][r] ) % mod;}printf( "%lld\n", f[1][n] );return 0;
}

回文

problem

题目链接


solution

这道题比前面的题可能还要简单一点。

会发现,每次选择最左端或者最右端的数字,连续选择对应在中间的序列也必须是连续的。

i.e.

1....213....3 选最左边的 111,接着选最右边的 333bbb 序列里面就是 13...,为了最后的回文,最后几次操作必须是选 333 后立马选 111

那会不会是 1...123....3 这种呢,123 貌似可以不相邻成为两端。

显然不可能,先选的 13... 之后才选择 222 ,那么回文就必须先选 222,再选 31,而 222 都被 111333 堵死了。

所以这就是一个贪心模拟的过程。

优先从左边选择开始模拟。


code

#include <cstdio>
#define maxn 1000005
int T, n, flag;
int a[maxn], ans[maxn];
int pos[2][maxn];void print() {int l = 1, r = n << 1;for( int i = 1;i <= ( n << 1 );i ++ )if( ans[i] == l ) printf( "L" ), l ++;else printf( "R" ), r --;printf( "\n" );
}void solve( int l, int r, int L, int R ) {for( int i = 2;i <= n;i ++ ) {if( l < L ) {if( pos[1][a[l]] == L - 1 ) { ans[i] = l ++, ans[(n << 1 | 1) - i] = -- L; continue; }if( pos[1][a[l]] == R + 1 ) { ans[i] = l ++, ans[(n << 1 | 1) - i] = ++ R; continue; }}if( r > R ) {if( pos[0][a[r]] == L - 1 ) { ans[i] = r --, ans[(n << 1 | 1) - i] = -- L; continue; }if( pos[0][a[r]] == R + 1 ) { ans[i] = r --, ans[(n << 1 | 1) - i] = ++ R; continue; }}flag = 0;return;}
}int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) pos[0][i] = pos[1][i] = 0;for( int i = 1;i <= ( n << 1 );i ++ ) {scanf( "%d", &a[i] );if( ! pos[0][a[i]] ) pos[0][a[i]] = i;else pos[1][a[i]] = i;}flag = 1;ans[1] = 1, ans[n << 1] = pos[1][a[1]];solve( 2, n << 1, pos[1][a[1]], pos[1][a[1]] );if( flag ) { print(); continue; }flag = 1;ans[1] = n << 1, ans[n << 1] = pos[0][a[n << 1]];solve( 1, (n << 1) - 1, pos[0][a[n << 1]], pos[0][a[n << 1]] );if( flag ) { print(); continue; }printf( "-1\n" );}return 0;
}

交通规划

problem

题目链接


solution

只能黑白染色,然后端点颜色不同的边就会计算贡献。

如果想到了,就是非常明显的网络流。

这种平面图般的网络流是很经典的有最短路优化——BZOJ上有一题网络流的经典“狼抓兔子”。

就算不会最短路优化也是可以暴力上网络流硬跑前 60′60'60 的部分分。


code-60‘

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define inf 1e18
#define maxn 505
#define Maxn 260000
#define maxm 1200000
#define int long long
queue < int > q;
struct node { int to, nxt, flow; }E[maxm];
int n, m, T, cnt, N, s, t, k;
int head[Maxn], cur[Maxn], dis[Maxn];
int a[maxn][maxn], b[maxn][maxn];void addedge( int u, int v, int flow ) {E[cnt] = { v, head[u], flow };head[u] = cnt ++;E[cnt] = { u, head[v], flow };head[v] = cnt ++;
}bool bfs() {memset( dis, 0, sizeof( dis ) );dis[s] = 1, q.push( s );while( ! q.empty() ) {int u = q.front(); q.pop();for( int i = cur[u] = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( ! dis[v] and E[i].flow ) {dis[v] = dis[u] + 1;q.push( v );}}}return dis[t];
}int dfs( int u, int cap ) {if( u == t or ! cap ) return cap;int flow = 0;for( int i = cur[u];~ i;i = E[i].nxt ) {cur[u] = i; int v = E[i].to;if( dis[v] == dis[u] + 1 ) {int w = dfs( v, min( cap, E[i].flow ) );if( ! w ) continue;E[i ^ 1].flow += w;E[i].flow -= w;flow += w;cap -= w;if( ! cap ) break;}}return flow;
}int dinic() {int ans = 0;while( bfs() ) ans += dfs( s, inf );return ans;
}int id( int i, int j ) { return ( i - 1 ) * m + j; }signed main() {scanf( "%lld %lld %lld", &n, &m, &T );for( int i = 1;i < n;i ++ ) for( int j = 1;j <= m;j ++ ) scanf( "%lld", &a[i][j] );for( int i = 1;i <= n;i ++ ) for( int j = 1;j < m;j ++ ) scanf( "%lld", &b[i][j] );while( T -- ) {cnt = 0, memset( head, -1, sizeof( head ) );scanf( "%lld", &k );N = n * m, s = N + k + 1, t = s + 1;for( int i = 1;i < n;i ++ ) for( int j = 1;j <= m;j ++ ) addedge( id(i, j), id(i + 1, j), a[i][j] );for( int i = 1;i <= n;i ++ ) for( int j = 1;j < m;j ++ ) addedge( id(i, j), id(i, j + 1), b[i][j] );for( int i = 1;i <= N;i ++ ) addedge( s, i, 0 ), addedge( i, t, 0 );for( int i = 1, w, x, c;i <= k;i ++ ) {scanf( "%lld %lld %lld", &w, &x, &c );++ N; int pos;if( x <= m ) pos = id( 1, x );else if( x <= n + m ) pos = id( x - m, m );else if( x <= n + m * 2 ) pos = id(n, 2 * m + n - x + 1);else pos = id( 2 * ( m + n ) - x + 1, 1 );addedge( N, pos, w );if( c ) addedge( s, N, w );else addedge( N, t, w );}printf( "%lld\n", dinic() );}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P1247 取火柴游戏

P1247 取火柴游戏 题意&#xff1a; 有n堆火柴&#xff0c;两个人轮流操作&#xff0c;每次只能在从一堆中取若干火柴&#xff0c;拿走最后一根火柴的为胜者&#xff0c;给你一个状态&#xff0c;问先手是赢是输 题解&#xff1a; 很经典的nim博弈&#xff0c;结论大家应该…

Codeforces:779(div2)

前言 solve 4 rnk247 占了罚时的便宜。 CF不占罚时便宜就会被罚时占便宜 感觉这场似乎都是性质题&#xff0c;一眼看出性质就秒了&#xff0c;看不出就很难做出来了。 C似乎卡了很多人。但我做起来还好。 D2做不出来有些懊恼。 E是妙题。 题目 A 水题&#xff0c;保证male…

我们为什么要搞长沙.NET技术社区(4)

我们为什么要搞长沙.NET技术社区&#xff08;4&#xff09;邹溪源&#xff0c;2019年3月7日Ps:文中的.NET 包括且不限定于传统.NET Framework技术和.NET Core技术。1. 楔子昨天&#xff08;2019年3月6日&#xff09;晚餐时间&#xff0c;有幸得到长沙技术圈资深.NET开发者出生…

P1290 欧几里德的游戏

P1290 欧几里德的游戏 题意&#xff1a; 给定两个正整数 M 和 N&#xff0c;从 Stan 开始&#xff0c;从其中较大的一个数&#xff0c;减去较小的数的正整数倍&#xff0c;当然&#xff0c;得到的数不能小于 0。然后是 Ollie进行同样的操作&#xff0c;直到一个人得到0&#…

【无码专区3】乘法表的解密破译

因为只有std&#xff0c;没有自我实现&#xff0c;所以是无码专区 problem 给定一个 qqq 进制的乘法表&#xff0c;每个字符代表着 0∼p−10\sim p-10∼p−1 不同的数字。 求每个字符代表的数字。保证有解。 \timesABCDACDBBDCBABBBBBBBBBCDCBBDBBCDBABBBCBD i.e. CD\text{C…

CF1553H XOR and Distance (Trie)

解析 有的时候&#xff0c;看起来是暴力的东西再稍微想想性质就是正解了。 本题有两种做法&#xff0c;一种使用了trie树&#xff0c;一种没有。但本质是一样的&#xff0c;只是trie树把我们的所求显性的表达了出来。 考虑trie树暴力怎么做。 对于一个特定的 xxx 走到一个结…

C#机器学习之判断日报是否合格

原文作者&#xff1a;心莱科技肖鑫简单来说机器学习的核心步骤在于“获取学习数据&#xff1b;选择机器算法&#xff1b;定型模型&#xff1b;评估模型&#xff0c;预测模型结果”&#xff0c;下面本人就以判断日报内容是否合格为例为大家简单的阐述一下C#的机器学习。第一步&a…

【无码专区4】幸运数字4(折半搜索+计数+结论)

因为只有std&#xff0c;没有自我实现&#xff0c;所以是无码专区 主要是为了训练思维能力 solution才是dls正解&#xff0c;但是因为只有潦草几句&#xff0c;所以大部分会有我自己基于正解上面的算法实现过程&#xff0c;可能选择的算法跟std中dls的实现不太一样。 std可能…

P1288 取数游戏II

P1288 取数游戏II 题意&#xff1a; 一个环&#xff0c;由边权&#xff0c;硬币一开始在一个点上&#xff0c;两个人轮流操作&#xff0c;每次操作向左或右移动&#xff0c;每次移动必须将边权减少到非负整数&#xff0c;如果原本是0则不能走&#xff0c;当不能走动时&#x…

CF1616F Tricolor Triangles(构造、高斯消元)

解析 关键性质&#xff1a;三元环合法等价于边权和模3等于0。 还有一个常识&#xff1a;三元环的级别是O(mm)O(m\sqrt m)O(mm​)。 证明&#xff1a; 三个点度数都大于 m\sqrt mm​ 的点不超过Cm3mmC_{\sqrt m}^3m\sqrt mCm​3​mm​ 个。 如果含有度数小于m\sqrt mm​ 的点&am…

SignalR2结合ujtopo实现拓扑图动态变化

上一篇文章基于jTopo的拓扑图设计工具库ujtopo&#xff0c;介绍了拓扑设计工具&#xff0c;这一篇我们使用SignalR2结合ujtopo实现拓扑图的动态变化。仅仅作为演示&#xff0c;之前的文章SignalR2简易数据看板演示&#xff0c;用一个小的示例演示了SignalR作为数据看板的用法&a…

树的同构模板题(法1.最小表示法+法2.树哈希)

树的同构problemsolutioncodesolutioncodeproblem 模板题 solution Ⅰ. 最小表示法 将树转化为 0/10/10/1 括号序列&#xff1a;从根开始 dfs\text{dfs}dfs&#xff0c;000 就往下遍历一个儿子&#xff0c;111 就返回&#xff0c;构成一个 2n2\times n2n 的括号序列。 显然…

CF917B MADMAX

CF917B MADMAX 题意&#xff1a; Alice和Bob有一个n个点m条边的DAG&#xff0c;每条边上有一个小写英文字母表示权值&#xff0c;Alice和Bob每人有一个棋子&#xff0c;每个人放在一个节点上&#xff08;可以放在同一个节点上&#xff09;。 第一轮Alice可以沿一条边把棋子移…

CF1534F:Falling Sand(tarjan、贪心、dp)

解析 本题做的过程大概是&#xff1a;到了正解门口决定回头&#xff0c;绕了地球一圈最后从另一边走到正解了… 我的分析&#xff1a; 首先 easy version 很简单&#xff0c;如果从一列最大值可以走到另一列最大值&#xff0c;那么后者就没用了。缩完点所有的零度点就是答案。…

Ocelot 入门Demo系列(01-Ocelot极简单Demo及负载均衡的配置)

来源&#xff1a;https://www.cnblogs.com/7tiny/p/10493805.html【前言】Ocelot是一个用.NET Core实现并且开源的API网关&#xff0c;它功能强大&#xff0c;包括了&#xff1a;路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterf…

CF464E The Classic Problem(主席树+哈希+最短路)

CF464E The Classic Problemproblemsolutioncodeproblem 题目链接 solution 经典题。 本题很特别的是每条边的边权都是 222 的幂&#xff0c;而且数据读入的是指数。 所以可以将路径权值看作一个二进制串&#xff0c;每加一条边就是对应二进制位 111&#xff0c;当然会有相…

CF1192B Dynamic Diameter(LCT)

Foreword\text{Foreword}Foreword zhengrunzhe 大佬的矩阵做法过于神奇&#xff0c;蒟蒻无法理解… 欧拉序的做法确实非常巧妙&#xff0c;但我也想不到这么神仙的做法… 提供一种可能简单一些的 LCT 做法。 由于本人 LCT 无法像大佬那么神&#xff0c;讲的会比较详细一些&…

博弈论(基础概念+例题)

博弈论(b站视频) 文章目录一些概念以Nim游戏为例Nim游戏介绍定义 必败/必胜局面必败/必胜局面的判定引理Nim游戏判定引理的等价命题有向图游戏对判定引理的数学描述-Sg函数有向图游戏的和题目&#xff1a;[有向图游戏][有向图游戏的和][构造/转化类]一些概念 以Nim游戏为例 Ni…

.NET Core 3.0 linux 部署小贴士

dotnet core 3.0 目前还是测试版&#xff0c;在linux下安装 sdk 需要有一些注意事项1.下载urlhttps://dotnet.microsoft.com/download/thank-you/dotnet-sdk-3.0.100-preview-009812-linux-x64-binaries2.安装指令mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-3.0.100…

莓良心(第二类斯特林数)

莓良心problemsolutioncodeproblem 莓在执行任务时&#xff0c;收集到了 nnn 份岩浆能源&#xff0c;其中第 iii 份的能量值是 wiw_iwi​ &#xff0c;她 决定将它们分成恰好 kkk 组带回基地&#xff0c;每一组都要有至少 111 份能源。 每一组能源会对运输设备产生负荷值&…