【CCF】NOI Online能力测试 提高组题目+解析+代码

解析和代码由杭州二中信奥队提供

序列

【题目描述】

小 D 有一个长度为 n 的整数序列 ai(下标从 1 开始编号,下同),她想通过若干次操作把它变成序列 bi。

小 D 有 m种可选的操作,第 i 种操作可使用三元组 (ti,ui,vi) 描述:若 ti=1,则她可以使 aui 与 avi 都加一或都减一;若 ti=2,则她可以使 aui-1、avi+1,或是 aui+1、avi-1,因此当 ui=vi 时,这种操作相当于没有操作。

小 D 可以以任意顺序执行操作,且每种操作都可进行无限次。现在给定序列与所有操作,请你帮她判断是否存在一种方案能将 ai 变为 bi。题目保证两个序列长度都为 n。若方案存在请输出 YES,否则输出 NO

【输入格式】

从 sequence.in 读入数据。
本题输入文件包含多组数据。
第一行一个正整数 T 表示数据组数。对于每组数据:
第一行两个整数 n,m,表示序列长度与操作种数。
第二行 n 个整数表示序列 ai。
第三行 n 个整数表示序列 bi。
接下来 m 行每行三个整数 ti,ui,vi,第 i 行描述操作 i。
注意:同一个三元组 (ti,ui,vi) 可能在输入中出现多次。

【输出格式】

输出到文件 sequence.out 中。
对于每组数据输出一行一个字符串 YESNO 表示答案。

【样例1输入】

3
1 1
1
3
1 1 1
2 3
1 2
4 5
1 1 2
2 1 2
1 1 2
3 3
1 2 3
5 5 4
1 1 2
1 1 3
2 2 3

【样例1输出】

YES
YES
YES

【样例1解释】

第一组数据:使用一次操作 1。第二组数据:使用三次操作 1。第三组数据:使用三次操作 1,令 a1,a2 都增加 3,再使用一次操作 2,令 a1,a3 都增加 1。

【数据范围与提示】

对于测试点 1 - 5:n=2,m=1,ai,bi ≤ 99,u1 ≠ v1,t1=1。
对于测试点 6 - 10:n=2,m=1,ai,bi ≤ 99,u1 ≠ v1,t1=2。
对于测试点 11 - 12:n=2,ai,bi ≤ 99,ui ≠ vi。
对于测试点 13 - 16:ti=2。
对于测试点 17:n,m ≤ 20。
对于测试点 18:n,m ≤ 1000。
对于所有测试点:1 ≤ T ≤ 10,1 ≤ n,m ≤ 105,1 ≤ ai,bi ≤ 109,ti ∈ {1,2},1≤ ui,vi≤ n。

【时间限制】

2.0s

【空间限制】

256MB

【上传文件】

上传c, cpp或pas语言源程序,文件名应依次为sequence.c, sequence.cpp, sequence.pas。

【解析】

我们令vali =ai - bi;,显然只需要对val数组进行操作,使它变成全0即呵。
把第二种操作提取出来,在ui和vi之间连一边,在某个联通块内如果val的和等于0,就可以构造出一组使这个联通块变为全0的方案。我们将其缩点,就变成了没有二操作的情况,这个时候考虑一个联通块是不是二分图,如果是二分图, 只需要判断二分图两边的val之和是否相等,否则判断val之和的奇偶性。构造方案留作思考。

【代码】

在这里插入图片描述

冒泡排序

【题目描述】

给定一个 1 ~ n 的排列 pi,接下来有 m 次操作,操作共两种:

  1. 交换操作:给定 x,将当前排列中的第 x 个数与第 x+1 个数交换位置。
  2. 询问操作:给定 k,请你求出当前排列经过 k 轮冒泡排序后的逆序对个数。
    对一个长度为 n 的排列 pi 进行一轮冒泡排序的伪代码如下:
    for i = 1 to n-1 :
        if p[i] > p[i + 1] :
            swap(p[i], p[i + 1])

【输入格式】

从文件 bubble.in 中读入数据。
第一行两个整数 n,m,表示排列长度与操作个数。
第二行 n 个整数表示排列 pi。
接下来 m 行每行两个整数 ti,ci,描述一次操作:若 ti=1,则本次操作是交换操作,x=ci;若 ti=2,则本次操作是询问操作,k=ci。

【输出格式】

输出到文件 bubble.out 中。
对于每次询问操作输出一行一个整数表示答案。

【样例1输入】

3 6
1 2 3
2 0
1 1
1 2
2 0
2 1
2 2

【样例1输出】

0
2
1
0

【样例1解释】

第一次操作:排列为 {1,2,3},经过 0 轮冒泡排序后为 {1,2,3},0 个逆序对。
第二次操作:排列变为 {2,1,3}。
第三次操作:排列变为 {2,3,1}。
第四次操作:经过 0 轮冒泡排序后排列变为 {2,3,1},2 个逆序对。
第五次操作:经过 1 轮冒泡排序后排列变为 {2,1,3},1 个逆序对。
第六次操作:经过 2 轮冒泡排序后排列变为 {1,2,3},0 个逆序对。

【数据范围与提示】

对于测试点 1 ~ 2:n,m ≤ 100。
对于测试点 3 ~ 4:n,m ≤ 2000。
对于测试点 5 ~ 6:交换操作个数不超过 100。
对于所有测试点:2 ≤ n,m ≤ 2 × 105,ti ∈ {1,2},1 ≤ x < n,0 ≤ k < 231。

【时间限制】

1.0s

【空间限制】

256MB

【上传文件】

上传c, cpp或pas语言源程序,文件名应依次为bubble.c, bubble.cpp, bubble.pas。

【解析】

在这里插入图片描述

【代码】

在这里插入图片描述

最小环

【题目描述】

给定一个长度为 n 的正整数序列 ai,下标从 1 开始编号。我们将该序列视为一个首尾相邻的环,更具体地,对于下标为 i,j(i ≤ j) 的两个数 ai,aj,它们的距离为 min(j-i,i+n-j)。

现在再给定 m 个整数 k1,k2,…,km,对每个 ki(i=1,2,…,m),你需要将上面的序列 ai 重新排列,使得环上任意两个距离为 ki 的数字的乘积之和最大。

【输入格式】

从文件ring.in中读入数据。
第一行两个正整数 n,m,表示序列长度与询问数。
接下来一行 n 个正整数表示 ai。
接下来 m 行每行一个非负整数表示 ki。

【输出格式】

输出到文件ring.out中。
共 m 行,每行一个整数表示答案。

【样例1输入】

6 3
1 2 3 4 5 6
0
1
2

【样例1输出】

91
82
85

【样例1解释】

ki=0 时:答案为每个数平方的和。
ki=1 时:一种最优方案:{3,1,2,4,6,5}。
答案为 3 × 1 + 1 × 2 + 2 × 4 + 4 × 6 + 6 × 5 + 5 × 3 = 82。
ki=2 时:一种最优方案:{3,6,1,4,2,5}。
答案为 3 × 1 + 1 × 2 + 2 × 3 + 6 × 4 + 4 × 5 + 5 × 6 = 85。

【数据范围与提示】

对于所有测试数据:1 ≤ m ≤ n ≤ 2 × 105,0 ≤ k ≤ ⌊n/2⌋,1 ≤ ai ≤ 105。
每个测试点的具体限制见下表:

测试点编号 n ≤ 特殊性质
1 10
2 18
3 36 n 为偶数且 m=1,k=2
4,5 1000 m ≤ 10,k=1
6 50 m ≤ 10,k ≤ 2
7,8 3000
9,10 2 × 105

【时间限制】

2.0s

【空间限制】

256MB

【上传文件】

上传c, cpp或pas语言源程序,文件名应依次为ring.c, ring.cpp, ring.pas。

【解析】

在这里插入图片描述

【代码】

在这里插入图片描述

发布了73 篇原创文章 · 获赞 94 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/104711077