Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine)) A-F全题解

Codeforces Round #740 (Div. 2, based on VK Cup 2021 - Final (Engine))

文章目录

  • A. Simply Strange Sort
  • B. Charmed by the Game
  • C. Deep Down Below
  • D1/D2. Up the Strip
  • E. Bottom-Tier Reversals
  • F. Top-Notch Insertions

A. Simply Strange Sort

签到题,暴力做

#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 1000
int n, T;
int a[maxn];int main() {scanf( "%d", &T );while( T -- ) {scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) scanf( "%d", &a[i] );int ans = 0;for( int i = 1;i;i ++ ) {for( int j = ( i & 1 ? 1 : 2 );j < n;j += 2 )if( a[j] > a[j + 1] ) swap( a[j], a[j + 1] ), ans = i;bool flag = 1;for( int j = 1;j < n;j ++ )if( a[j] > a[j + 1] ) {flag = 0;break;}if( flag ) break;}printf( "%d\n", ans );}return 0;
}

B. Charmed by the Game

简单题

分总场数n=a+bn=a+bn=a+b的奇偶讨论,假设以Alice Bob第一场发球

算出每个人发球的场数,计算出某个胜场不够的人至少要break多少场

之后只能两人相互break相同场数才能保持彼此赢的场数满足a/b

vis[i]记录break恰好iii场是否可以,每次都是+2+2+2暴力加

碰到已经打过标记的就可以跳出循环

#include <cstdio>
#define maxn 200005
int ans;
bool vis[maxn];int main() {int T, a, b, n, ta, tb;scanf( "%d", &T );while( T -- ) {scanf( "%d %d", &a, &b );n = a + b, ans = 0;for( int i = 0;i <= n;i ++ ) vis[i] = 0;if( n & 1 ) {ta = ( n + 1 ) >> 1, tb = n >> 1;if( ta < a )for( int i = a - ta;i <= a - ta + 2 * b;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;elsefor( int i = b - tb;i <= b - tb + 2 * a;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;ta = n >> 1, tb = ( n + 1 ) >> 1;if( ta < a )for( int i = a - ta;i <= a - ta + 2 * b;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;elsefor( int i = b - tb;i <= b - tb + 2 * a;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;}else {ta = tb = n >> 1;if( ta < a )for( int i = a - ta;i <= a - ta + 2 * b;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;elsefor( int i = b - tb;i <= b - tb + 2 * a;i += 2 )if( ! vis[i] ) vis[i] = 1; else break;}for( int i = 0;i <= n;i ++ ) ans += vis[i];printf( "%d\n", ans );for( int i = 0;i <= n;i ++ ) if( vis[i] ) printf( "%d ", i );printf( "\n" );}return 0;
}

C. Deep Down Below

简单题

贪心

考虑要通过一个洞穴,初始带的力量值最小是多少

显然为max⁡{armori+1−(i−1)}\max\Big\{armor_i+1-(i-1)\Big\}max{armori+1(i1)}

在第iii个怪物前面可以有i−1i-1i1个怪物杀死获得提升的机会,然后要求严格大于怪物生命值,所以+1+1+1

将这个值定义为洞穴的通关要求,升序排列洞穴

每次通过一个洞穴力量值就会增加洞穴的怪物数那么大

在下一个洞穴前判断能否通过,不能就加上差的力量值

#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long
#define maxn 100005
struct node { int id, val, k; }armor[maxn];
int T, n;signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld", &n );for( int i = 1, x;i <= n;i ++ ) {armor[i].id = i, armor[i].val = 0;scanf( "%lld", &armor[i].k );for( int j = 1;j <= armor[i].k;j ++ ) {scanf( "%lld", &x );armor[i].val = max( armor[i].val, x + 1 - ( j - 1 ) );}}sort( armor + 1, armor + n + 1, []( node x, node y ) { return x.val < y.val; } );int ans = armor[1].val, now = armor[1].val;for( int i = 1;i <= n;i ++ )if( now >= armor[i].val ) now += armor[i].k;else ans += armor[i].val - now, now = armor[i].val + armor[i].k;printf( "%lld\n", ans );}return 0;
}

D1/D2. Up the Strip

简单DPDPDP

设计fi:f_i:fi: 移动到格子iii的方案数,由n→1n\rightarrow 1n1转移

  • iii后面的每个格子都可以通过−x-xx的操作转移过来

    fi+=∑j=i+1nfjf_i+=\sum_{j=i+1}^nf_jfi+=j=i+1nfj

  • iii后面的格子(以2∗i2*i2i开始)都可以通过/x/x/x的操作转移过来

    但是因为是下取整,所以有的jjj,可能除以多个xxx都能转移到iii,不能简单只加一个fjf_jfj完事

    不妨反其道而行之,枚举xxx,计算出区间[l,r][l,r][l,r]满足j∈[l,r],⌊jx⌋=ij\in[l,r],\lfloor\frac{j}{x}\rfloor=ij[l,r],xj=i

    很简单的数学计算一下,l=i∗x,r=x∗(i+1)−1l=i*x,r=x*(i+1)-1l=ix,r=x(i+1)1

    fi+=∑j=lrfjf_i+=\sum_{j=l}^rf_jfi+=j=lrfj

    时间复杂度是调和级数,logn\rm lognlogn

后缀优化即可,sumi=∑j=infjsum_i=\sum_{j=i}^nf_jsumi=j=infj

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define maxn 4000005
int n, mod;
int f[maxn], sum[maxn];signed main() {scanf( "%lld %lld", &n, &mod );f[n] = sum[n] = 1;for( int i = n - 1;i;i -- ) {f[i] = sum[i + 1];for( int j = 2;i * j <= n;j ++ ) {int l = i * j, r = min( n, j * ( i + 1 ) - 1 );f[i] = ( f[i] + sum[l] - sum[r + 1] + mod ) % mod;}sum[i] = ( sum[i + 1] + f[i] ) % mod;}printf( "%lld\n", f[1] );return 0;
}

E. Bottom-Tier Reversals

勉强中档题

限制次数为5n2\frac{5n}{2}25n,且只能操作奇数

暗示构造,且相邻奇偶绑定在一起才行

也就是说能否寻找一种构造

555次操作内,将i,i−1i,i-1i,i1放到相应位置且以后不再操作这两个数,操作范围变成i−2i-2i2

observation : 每次操作[1,x][1,x][1,x]i↔x−i+1i\leftrightarrow x-i+1ixi+1x+1x+1x+1为偶数,所以i,x−i+1i,x-i+1i,xi+1同奇偶

最后要满足a[i]=i,下标必须和值是同奇偶才会有解

判完无解后,555次操作这是可以做到的

  • n→1n\rightarrow 1n1构造,每次满足n,n−1n,n-1n,n1iii为奇数)放到相应位置,每次操作后范围n−=2n-=2n=2
  • 找到iii的位置xxx(显然xxx为奇数),第一次操作[1,x][1,x][1,x]区间,使得iii成为序列第一个
  • 找到i−1i-1i1的位置yyy(显然yyy为偶数),第二次操作[1,y−1][1,y-1][1,y1]区间,使得iii成为i−1i-1i1前面一个
  • 第三次操作[1,y+1][1,y+1][1,y+1],使得i−1i-1i1成为序列第二个,iii成为序列第三个
  • 第四次操作[1,3][1,3][1,3],使得i−1i-1i1成为序列第二个,iii成为序列第一个
  • 第五次操作[1,n][1,n][1,n],使得iii成为序列最后一个,i−1i-1i1成为序列倒数第二个
  • 满足条件
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 2025
int T, n, cnt;
int p[maxn], id[maxn], ans[maxn << 2];void Reverse( int len ) {ans[++ cnt] = len;for( int i = 1;i <= len;i ++ )id[p[i]] = len - id[p[i]] + 1;reverse( p + 1, p + len + 1 );
}int main() {scanf( "%d", &T );next :while( T -- ) {cnt = 0;scanf( "%d", &n );for( int i = 1;i <= n;i ++ ) {scanf( "%d", &p[i] );id[p[i]] = i;}for( int i = 1;i <= n;i ++ )if( ( p[i] & 1 ) ^ ( i & 1 ) ) {printf( "-1\n" );goto next;}for( int i = n;i > 1;i -= 2 ) {Reverse( id[i] );int x = id[i - 1];Reverse( x - 1 );Reverse( x + 1 );Reverse( 3 );Reverse( i );}printf( "%d\n", cnt );for( int i = 1;i <= cnt;i ++ )printf( "%d ", ans[i] );printf( "\n" );}return 0;
}

F. Top-Notch Insertions

困难

observation : 根据输入的mmm个操作,最后序列上放的下标是固定的

e.g. a1,a2,a3,a4,a5a_1,a_2,a_3,a_4,a_5a1,a2,a3,a4,a5,操作(3,1) (4,1) (5,3)后,一定是a4,a3,a5,a1,a2a_4,a_3,a_5,a_1,a_2a4,a3,a5,a1,a2,不管aia_iai的值真的是多少

假设最后排序后的序列为[b1,b2,...,bn][b_1,b_2,...,b_n][b1,b2,...,bn]

根据题目知,∀i∈[1,n)bi≤bi+1\forall_i\in[1,n)\quad b_i\le b_{i+1}i[1,n)bibi+1

考虑iii,如果a[i]>=a[i-1],不发生排序,并不能告诉我们什么东西,最多能知道最后bbb序列中aia_iai排在ai−1a_{i-1}ai1的后面某个位置

那么如果aia_iai插到jjj位置,能说明什么?

  • a[i]<a[j]
  • a[i]>=a[j-1]

同样的不等式不能提供有用的帮助,反而重要的是a[i]<a[j]这个条件

我们非常关心aia_iai,满足ai−1a_{i-1}ai1被插入,这意味着ai−1<aia_{i-1}<a_iai1<ai(注意是严格小于)

其余的相邻两个数关系可能是小于,可能是小于等于

换言之,最后的bbb序列,有些位置被打了标记,强制该位置前一个的值严格小于改位置的值

设被标记位置的个数为cnt\rm cntcnt,则最后的答案为(2n−cnt−1n)\binom{2n-cnt-1}{n}(n2ncnt1)

  • 考虑ii∈[1,n)i\quad i\in[1,n)ii[1,n)bi≤bi+1b_{i}\le b_{i+1}bibi+1,让iii后面所有的bbb+1+1+1,变成bi<bi+1b_i<b_{i+1}bi<bi+1
  • 现在有∀ibi<bi+1\forall i\quad b_i<b_{i+1}ibi<bi+1
  • 最大的bbb取值可以为n+n−1−cntn+n-1-cntn+n1cnt
  • 相当于在[1,maxB][1,\rm maxB][1,maxB]中选nnn互不相同的数

至于怎么找该被标记的数

  • 相当于需要一种数据结构支持查找第kkk
  • 线段树就可以了

注意本题只保证了mmm的限制,没有nnn的限制

所以需要都回滚

那么就需要记录每次问题后的操作点

#include <cstdio>
#define maxn 200005
#define int long long
#define mod 998244353
#define lson num << 1
#define rson num << 1 | 1
int n, m, T;
bool vis[maxn];
int x[maxn], y[maxn], id[maxn], pos[maxn];
int fac[maxn << 1], inv[maxn << 1], t[maxn << 2];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void init( int n ) {fac[0] = inv[0] = 1;for( int i = 1;i <= n;i ++ ) fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- ) inv[i] = inv[i + 1] * ( i + 1 ) % mod;
}int C( int n, int m ) {return fac[n] * inv[m] % mod * inv[n - m] % mod;
}void build( int num, int l, int r ) {t[num] = r - l + 1;if( l == r ) return;int mid = l + r >> 1;build( lson, l, mid );build( rson, mid + 1, r );
}int findKth( int k, int num = 1, int l = 1, int r = 2e5 ) {t[num] --;//找第K大的时候 顺便完成-1的修改 if( l == r ) return l;int mid = l + r >> 1;if( k <= t[lson] ) return findKth( k, lson, l, mid );else return findKth( k - t[lson], rson, mid + 1, r );
}void modify( int k, int num = 1, int l = 1, int r = 2e5 ) {t[num] ++;if( l == r ) return;int mid = l + r >> 1;if( k <= mid ) modify( k, lson, l, mid );else modify( k, rson, mid + 1, r );
}int query( int k, int num = 1, int l = 1, int r = 2e5 ) {if( l == r ) return l;int mid = l + r >> 1;if( k <= t[lson] ) return query( k, lson, l, mid );else return query( k - t[lson], rson, mid + 1, r );
}signed main() {init( 4e5 );build( 1, 1, 2e5 );scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &n, &m );for( int i = 1;i <= m;i ++ )scanf( "%lld %lld", &x[i], &y[i] );int cnt = 0;for( int i = m;i;i -- ) {id[i] = query( y[i] + 1 );if( ! vis[id[i]] ) cnt ++, vis[id[i]] = 1;pos[i] = findKth( y[i] );}printf( "%lld\n", C( 2 * n - 1 - cnt, n ) );for( int i = m;i;i -- )vis[id[i]] = 0, modify( pos[i] );}return 0;
}

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

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

相关文章

[小技巧]C#中如何为枚举类型添加描述方法

背景在我们的日常开发中&#xff0c;我们会经常使用枚举类型。有时我们只需要显示枚举的值或者枚举值对应名称&#xff0c; 但是在某些场景下&#xff0c;我们可能需要将枚举值显示为不同的字符串。例&#xff1a; 当前我们有如下枚举Level这个枚举有4个可选值B, N, G, VG。 现…

Loj#3320-「CCO 2020」旅行商问题

正题 题目链接:https://loj.ac/p/3320 题目大意 有一张nnn个点的无向完全图&#xff0c;每一条边是红色或者蓝色&#xff0c;对于每个点sss求从这个点出发的一条尽量短的经过所有点的路径。 1≤n≤20001\leq n\leq 20001≤n≤2000 解题思路 显然地猜测一下最短的长度肯定是n…

AcWing 1087. 修剪草坪28

AcWing 1087. 修剪草坪 题意: 有n个数&#xff0c;不能选超过连续的k个数&#xff0c;问所能选的最大值是多少&#xff1f; 题解&#xff1a; 我们首先分析dp过程&#xff1a; dp[i]表示选择完前i个数的最大值 sum[i]表示前i项和 对于第i个数&#xff0c;它有两个情况&#…

洛谷P4463:calc(dp、拉格朗日插值)

Solution\text{Solution}Solution 神奇题目。 首先可以强制所有的数递增&#xff0c;最后的答案乘一个 n!n!n! 即可。 设 dpi,jdp_{i,j}dpi,j​ 表示在 [1,j][1,j][1,j] 的值域选了 iii 个数的答案&#xff0c;不难写出 dp 转移&#xff1a; dpi,jdpi−1,j−1jdpi,j−1dp_{i,j…

CF1710C-XOR Triangle【dp】

正题 题目链接:https://www.luogu.com.cn/problem/CF1710C 题目大意 求有多少对0≤a,b,c≤n0\leq a,b,c\leq n0≤a,b,c≤n满足axorb,axorc,bxorca\ xor\ b,a\ xor\ c,b\ xor\ ca xor b,a xor c,b xor c作为边长时能构成一个非退化三角形。 n以二进制形式给出 1≤n<221051…

工业通信的开源项目 HslCommunication 介绍

前言&#xff1a;本项目的孵化说来也是机缘巧合的事&#xff0c;本人于13年大学毕业后去了一家大型的国企工作&#xff0c;慢慢的走上了工业软件&#xff0c;上位机软件开发的道路。于14年正式开发基于windows的软件&#xff0c;当时可选的技术栈就是MFC和C#的winform&#xff…

【地狱副本】数据结构之线段树Ⅲ——区间最值/赋值/修改/历史值操作(HDU5306,Tyvj 1518,【清华集训2015】V,HDU6315,HDU1828,POJ3162)

文章目录Gorgeous SequenceTyvj 1518 CPU监控【清华集训2015】VNaive OperationsPictureWalking RaceGorgeous Sequence HDU5306 操作 区间与xxx取min\rm minmin查询区间最大值查询区间和 比较暴力的线段树维护区间 Max : 区间最大值sub_max : 严格小于最大值的区间次大值…

Acwing 1089. 烽火传递

Acwing 1089. 烽火传递 题意&#xff1a; 有n个数&#xff0c;要保证每m个数中必须选一个&#xff0c;问所选数的最小总和是多少 题解&#xff1a; 我一开始设的状态为:dp[i]表示前i个数选完的最小值&#xff0c;第i个数可以选也可以不选&#xff0c;但是这样一个状态&…

CF886E Maximum Element(dp、组合数学)

Solution\text{Solution}Solution 纯纯的dp题。 关键在于我们 dp 时只关注不同元素之间的相对大小。 非法情况不易统计&#xff0c;考虑转而考虑合法情况再用全排列减。 设计 fif_ifi​ 为长度为 iii 的排列循环到一直最后也没有跳出的方案数。 枚举最大的元素 iii 放置的位置…

IIS作为ASP.NET Core2.1 反向代理服务器未说的秘密

--以下内容针对 ASP.NET Core2.1&#xff0c;2.2出现IIS进程内寄宿 暂不展开讨论---相比ASP.NET&#xff0c;出现了3个新的组件:ASP.NET Core Module、Kestrel、dotnet.exe&#xff0c; 后面我们会理清楚这三个组件的作用和组件之间的交互原理。 ASP.NET Core 设计的初衷是开源…

CF1710B-Rain【堆】

正题 题目链接:https://www.luogu.com.cn/problem/CF1710B 题目大意 一个数轴&#xff0c;每个位置上开始时都有一个ax0a_x0ax​0&#xff0c;nnn次操作pi,hip_i,h_ipi​,hi​对于所有位置axa_xax​令其变为axmax⁡(hi−abs(pi−x),0)a_x\max(h_i-abs(p_i-x),0)ax​max(hi​−…

数据结构之线段树Ⅴ——(李超线段树)Robot,Product Sum,Building Bridges,Jump mission

文章目录RobotProduct SumBuilding BridgesJump missionRobot BZOJ3938 机器人每次一旦改变速度&#xff0c;直到下一次改变速度为止 这一时间段内机器人的位置下标可以用一次函数表示 如果知道时刻t1t_1t1​即将改变速度的机器人位置&#xff0c;以及最近的下一次机器人速…

模板:拉格朗日插值(多项式)

所谓拉格朗日插值&#xff0c;就是在“拉格朗日”进行的一项民俗活动。拉格朗日通常在每年2月的第82个星期三。 &#xff08;逃&#xff09; 前言 非常强大的算法。 当可以证明某个函数是一个 kkk 次多项式时&#xff0c;我们就可以插入 k1k1k1 个函数值并快速的求出我们要求…

程序员修神之路--分布式缓存的一条明路(附代码)

菜菜呀&#xff0c;由于公司业务不断扩大&#xff0c;线上分布式缓存服务器扛不住了呀程序员主力 Y总如果加硬件能解决的问题&#xff0c;那就不需要修改程序菜菜我是想加服务器来解决这个问题&#xff0c;但是有个问题呀程序员主力 Y总&#xff1f;&#xff1f;&#xff1f;菜…

2019 ICPC Asia Nanjing Regional

题号题目难度知识点AA Hard Problem签到题思维题BChessboardCDigital Path签到题dfs记忆化搜索DHolesEObservationFPaper GradingGPoker GameHPrince and Princess四稳铜快银思维题ISpace StationJSpyKTriangle三题快铜计算几何

uoj#751-[UNR #6]神隐【交互】

正题 题目链接:https://uoj.ac/problem/751 题目大意 有一棵nnn个点的树&#xff0c;你每次可以选择一个边集&#xff0c;交互库会返回你所有联通块&#xff0c;要求这棵树。 n≤2000n\leq 2000n≤2000&#xff0c;操作次数不超过141414。 或 n≤131072n\leq 131072n≤131072…

模板:快速莫比乌斯变换(FMT)+快速沃尔什变换(FWT)(多项式)

文章目录前言解析OR定义变换&#xff1a;逆变换代码AND代码XOR定义变换逆变换代码所谓快速沃尔什变换&#xff0c;就是快速的沃尔玛什锦专柜变换 &#xff08;逃&#xff09; 前言 正常卷积的定义&#xff1a;ck∑ijkaibjc_k\sum_{ijk}a_ib_jck​∑ijk​ai​bj​。 可以用FFT…

[AtCoder Beginner Contest 216] 题解

文章目录A - Signed DifficultyB - Same NameC - Many BallsD - Pair of BallsE - Amusement ParkF - Max Sum CountingG - 01Sequence比赛链接A - Signed Difficulty 签到题 #include <cstdio> int x, y; char c; int main() {scanf( "%d%c%d", &x, &am…

长沙.NET技术社区正式成立

感谢大家的关注&#xff0c;请允许我冒昧的向大家汇报长沙.NET技术社区第一次交流会的会议进展情况。活动过程汇报2019年2月17日&#xff0c;继深圳&#xff0c;广州&#xff0c;西安&#xff0c;成都&#xff0c;苏州相继成立了.net社区之后&#xff0c;酝酿已久的长沙.net社区…

A Hard Problem

A Hard Problem 题意&#xff1a; 给定一个n&#xff0c;要求找到最小的正数k&#xff0c;使得在集合T中任意选K个数&#xff0c;其中存在两个不同的u和v&#xff0c;u是v的因子 题解&#xff1a; 一开始想偏了&#xff0c;往质因数方向想了&#xff0c;然后因为1e9的以内的…