前面四道水题就不打了[Doge]
题目列表
Rotiraj
题目描述
Mislav 和 Marko 设计了一款新游戏,给它起了个名字 Rotate。首先,Marko 想好一个长度为 N 的整
数数列,并将其均分为若干部分,每一部分包含 K 个数字(K 能被 N 整除)。第一部分即序列中前 K 个数
字,第二部分即接下来的 K 个数字,以此类推。
然后 Marko 要求 Mislav 对序列进行一些操作,每个操作都是以下两种操作之一:
◆1 每个部分内部移动 X 次。
◆2 对于整个序列,移动 X 次。
注:如果 X>0,则向右移动 X 次;如果 X<0,则向左移动 X 次;如果 X=0,显然不移动.
输入输出格式
输入
第一行输入三个正整数 N,K 和 Q;N 表示序列的长度,K 表示每个部分有几个数字,Q 表示操作的次数。
接下来的 Q 行,每行包含两个整数 A 和 X;A 表示操作的类型是内部还是整个序列,X 表示移动的次数。
负数表示向左移动,而正数表示向右移动。
最后一行包含 N 个用空格分隔的整数 Zi 表示最终的序列(在进行了所有操作之后)。
输出
输出共一行,即初始时的数列,每两个整数之间用一个空格隔开。
输入输出样例
样例输入
4 2 2
2 2
1 1
3 2 1 0
样例输出
0 1 2 3
解题思路
每一组数属于一个小环,组与组之间又形成一个大环
所以倒着还原就行了
附上代码:
#include <iostream>
#include <cstdio>
const int MaxN = 100005;
using namespace std;
int N, K, M;
int Num, Id;
int Lst, Start;
int Ques[2][MaxN];
int A[MaxN];
int Wz[MaxN];
int Ans[MaxN];
inline void Read(int &Rem) {
Rem = 0;
int f = 1;
char ch = getchar();
for (; ! isdigit(ch); ch = getchar())if (ch == '-')f = -1;
for (; isdigit(ch); ch = getchar())Rem = (Rem << 1) + (Rem << 3) + (ch ^ 48);
Rem *= f;
return ;
}
void Work(int L,int R) {
++ Wz[L];
-- Wz[R];
if (L > R)++ Wz[0];
return ;
}
int main() {
Read(N); Read(K); Read(M);
Num = N / K;
for (int i = 0; i < M; ++ i) {
Read(Ques[0][M - 1 - i]);
Read(Ques[1][M - 1 - i]);
Ques[1][M - 1 - i] *= - 1;//因为是倒着回去操作的,所以就取相反数
}
for (int i = 0; i < N; ++ i) Read(A[i]);
for (int i = 0; i < M; ++ i) {
if (Ques[0][i] == 1)Ques[1][i] = (Ques[1][i] % K + K) % K;//小环中运动
if (Ques[0][i] == 2) {//大环运动
Ques[1][i] = (Ques[1][i] % N + N) % N;
Start = (Start + Ques[1][i] / K) % Num;
Ques[1][i] %= K;
Work((2 * K - Lst - Ques[1][i]) % K, (2 * K - Lst) % K);
}
Lst = (Lst + Ques[1][i]) % K;
}
for (int i = 0; i < K; ++ i) {
Start = ((Start + Wz[i]) % Num + Num) % Num;
Id = Start * K + (i + Lst) % K;
for (int j = 0; j < Num; ++ j) {
Ans[Id] = A[i + j * K];
Id = (Id + K) % N;
}
}
for (int i = 0; i < N; ++ i) //最后圆满输出
printf ("%d ", Ans[i]);
return 0;
}
Learning by Example
题目描述
FJ 已经认真阅读了关于机器学习的所有要点,通过这些既可以分析数据又可以获知大量有趣且意想
不到的信息(他甚至已经命名为“智能区域”!)。FJ 决定运用这个智能区域对他现有的牛群建立一个自
动分类器,可以猜测一头牛是否有斑点。
不幸的是 FJ 没有做好对他的奶牛数据的及时跟踪。对于他的 N 头奶牛,他所知道的是每头奶牛的
重量,但他却想了解每头奶牛是否有斑点,但每一头牛都有不同的重量。根据这个数据,他建立了所谓
的“近邻”。猜测某一头奶牛是否有斑点,FJ 首先找到和奶牛 C 体重最接近的奶牛 C’,如果奶牛 C 有
斑点,则判定 C’也有斑点。如果 C’位于两头分别有无斑点的奶牛的正中间,则 C’可能有也可能无斑
点。
FJ 想将这套系统在他买的奶牛身上试验一下。当测量了这些新奶牛的体重后,他知道这些奶牛的体
重位于 A 和 B 之间(含)。请根据 FJ 智能系统提供的信息,确定这些奶牛中最多有多少头会有斑点。需
要注意的是,分类器只决定使用 FJ 的现有奶牛数据,没有任何新的奶牛。还注意到,因为 A 和 B 都是
相当大的
输入输出格式
输入
第一行包含 3 个整数 N, A, B.
接下来 N 行,每行包含一个字符串和一个整数,字符串表示奶牛的斑点信息,整数表示奶牛的体重 W,S
表示为有斑点,NS 表示为无斑点。
输出
输出共一行一个整数,即统计[A,B]最多可能有斑点的奶牛总数。
输入输出样例
样例输入
3 1 10
S 10
NS 4
S 1
样例输出
6
解题思路
先将每一头牛的位置进行排序,相邻两头牛有四种情况:
1.两头都是有斑点的
那么两头牛之间的牛都是有斑点的
2.左边的牛有斑点,右边的牛没有斑点
因为是要求最多的有斑点的牛的数量,所以从左边的牛到中间的牛都是有斑点的牛
3.左边的牛没有斑点,右边的牛有斑点
因为是要求最多的有斑点的牛的数量,所以从中间的牛到右边的牛都是有斑点的牛
4.两头都是没有斑点的
那么中间的牛都没有斑点
四种情况都列出来的,那么只需要实现代码就可以了
附上代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
const int MaxN = 1e4 * 5 + 5;
using namespace std;
struct Cow {
bool Flg;
int Wz;
bool operator <(const Cow &y)const {//按位置进行排序
return Wz < y.Wz;
};
}W[MaxN];
int N, A, B;
long long Ans = 0;
int main() {
scanf ("%d %d %d", &N, &A, &B);
char c[3];
for (int i = 1; i <= N; ++ i) {
scanf ("%s %d", &c, &W[i].Wz);
if (c[0] == 'N')W[i].Flg = false;
else {
W[i].Flg = true;
if (W[i].Wz >= A && W[i].Wz <= B)//这头有斑点的牛在范围内直接++ Ans
++ Ans;
}
}
sort (W + 1, W + N + 1);//按位置进行排序
if ((W[1].Flg && W[1].Wz > B) || (W[N].Flg && W[N].Wz < A)) {//特判一下,A~B的范围如果在第一头牛的左边,或者最后一头牛的右边,那么可以直接求值
Ans += B - A + 1;
printf ("%lld\n", Ans);
return 0 ;
}
if (W[1].Flg && A < W[1].Wz) Ans += W[1].Wz - A;//如果范围的左边界在第一头牛的左边,如果第一头牛是有斑点的,那么就先把Ans加上
for (int i = 1; i < N; ++ i) {
int St, End;
int Mid = (W[i + 1].Wz - W[i].Wz >> 1) + W[i].Wz;
if (W[i].Flg == false && W[i + 1].Flg == false)continue ;//反正都没有,那就不加了
if (W[i].Flg == true && W[i + 1].Flg == false) {
St = max(A, W[i].Wz + 1), End = min(B, Mid);//左边到中间
if (End >= St)//不能少了这一句
Ans += End - St + 1;
}
if (W[i].Flg == true && W[i + 1].Flg == true) {
St = max(A, W[i].Wz + 1), End = min(B, W[i + 1].Wz - 1);//左到右全部
if (End >= St)
Ans += End - St + 1;
}
if (W[i].Flg == false && W[i + 1].Flg == true) {
if ((W[i].Wz & 1) ^ (W[i + 1].Wz & 1)) ++ Mid;//特判一下,如果左右牛的位置一个是奇数,一个是偶数,那么Mid的位置往后移一个
St = max(A, Mid), End = min(B, W[i + 1].Wz - 1);//中间到右边
if (End >= St)
Ans += End - St + 1;
}
}
if (W[N].Flg && W[N].Wz < B)//要是范围的右边界在最后一头牛的右边,Ans要加上
Ans += B - W[N].Wz;
printf ("%lld\n", Ans);
}
Painting The Barn-S
题目描述
Farmer John 不擅长多任务处理。他经常分心,很难完成长的项目。目前,他正试图在谷仓的一侧
上漆,但他一直在画小矩形区域,然后由于照料奶牛的需要而偏离了方向,使得谷仓的某些部分上漆的
涂料比其他部分多。
我们可以将谷仓的一侧描述为一个二维 xy 平面,Farmer John 在该平面上绘制 N 个矩形,每个矩
形的边都与坐标轴平行,每个矩形由谷仓的左下角和右上角点的坐标描述。
Farmer John 想在谷仓上涂几层油漆,这样在不久的将来就不需要再重新粉刷了。但是,他不想浪
费时间涂太多的油漆。结果表明,涂 K 层是最佳用量。请在他画完所有的小矩形后,帮他确定谷仓有
多少面积被 K 层油漆覆盖。
输入输出格式
输入
第 1 行包含 N 和 K;
接下来 N 行,每行包含四个整数 x1 y1 x2 y2;描述正在绘制的矩形区域,左下角(x1,y1)和右上
角(x2,y2)
输出
输出共一行一个整数,即谷仓被 K 层油漆覆盖的区域面积。
输入输出样例
样例输入
3 2
1 1 5 5
4 4 7 6
3 3 8 7
样例输出
8
解题思路
这题其实炒鸡水,说白了就是二维矩阵求面积
附上代码:
#include <iostream>
#include <cstdio>
const int MaxN = 1e3 + 5;
using namespace std;
int N, K, Ans;
int a[MaxN][MaxN],b[MaxN][MaxN];
int main() {
scanf ("%d %d", &N, &K);
for (int i = 1; i <= N; i ++) {
int x1,y1,x2,y2;
scanf ("%d %d %d %d", &x1, &y1, &x2, &y2);
a[x1 + 1][y1 + 1] += 1;
a[x2 + 1][y2 + 1] += 1;
a[x1 + 1][y2 + 1] -= 1;
a[x2 + 1][y1 + 1] -= 1;
}
for (int i = 1; i <= 1000; i ++) {
for (int j = 1; j <= 1000; j ++) {
b[i][j] = b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1] + a[i][j];
if(b[i][j] == K) Ans ++;
}
}
printf ("%d\n", Ans);
return 0;
}
这么水我就不多加注释了
Piggy Back
题目描述
Bessie 和她的姐姐 Elsie 在不同的田块吃草,晚上她们都返回牛棚休息。作为聪明的奶牛,她们想
设计一个方案使得步行消耗的能量最少。
Bessie 从一个田块到相邻的田块要耗费 B 个单位的能量,Elsie 从一个田块到相邻的田块要耗费 E
个单位的能量。然而当 Bessie 和 Elsie 处于同一个田块时,Bessie 用背驮着 Elsie 一起走,从一个田
块到相邻的田块要耗费 P 个单位的能量。如果 P 小于 B+E,则被认为是比较适用的;如果 P 非常小,那
么最佳的方案就是尽快使得 Bessie 和 Elsie 在某一田块相遇;当然如果 P 非常大,那么则尽可能使得
Bessie 和 Elsie 分开走。另一方面,她们对“背驮式”很不高兴,她们不明白为什么这种猪用来驮运的
方式会被认为是优秀的方法。
给出 B, E 和 P, 帮助她们姐俩找出从牧场到牛棚的花费能量最小的方案。
输入输出格式
输入
第一行包含 5 个正整数 B, E, P, N 和 M。 N 是牧场中田块的数量(分别编号为 1…N), M 表示田块
之间通路条数. Bessie 和 Elsie 一开始分别位于 1 和 2, 牛棚位于 N.
接下来 M 行,每行一对整数 U 和 V,分别表示两个田块之间有通路。通路连接是双向的,可以从 1 到 N,
和从 2 到 N,并且沿途有一系列通路。
输出
输出共一行一个整数,表示从牧场到牛棚的花费能量最小的方案。
输入输出样例
样例输入
4 4 5 8 8
1 4
2 3
3 4
4 7
2 5
5 6
6 8
7 8
样例输出
22
解题思路
三遍广搜,可以打一个函数,但是我没有打,导致代码非常的长
附上代码:
#include <iostream>
#include <cstdio>
#include <vector>
const int Inf = 2e9;
const int MaxN = 40005;
using namespace std;
int N,M;
int Tot;
int u, p, v, e, b;
int tail, head;
long long MinAns;
long long Dis1[MaxN], Dis2[MaxN], Dis3[MaxN], Q[MaxN], Q1[MaxN];
vector <int> To[MaxN];
inline void Read (int & Rem) {
char ch = getchar();
Rem = 0;
for (; ! isdigit(ch); ch = getchar());
for (; isdigit(ch); ch = getchar())Rem = (Rem << 1) + (Rem << 3) + (ch ^ 48);
return ;
}
int main() {
Read(b); Read(e); Read(p); Read(N); Read(M);
head = 0,tail = 0;
for (int i = 1; i <= M; i ++) {
int x, y;
Read(x); Read(y);//输入
To[x].push_back(y);
To[y].push_back(x);
}
for (int i = 1; i <= N; i ++) Dis1[i] = Dis2[i] = Dis3[i] = Inf;//初始化为无穷大
for (int i = 0; i < To[1].size(); i ++) {//先把第一个点能到的点入队
Q[++ tail] = To[1][i];
Dis1[To[1][i]] = b;
}
Dis1[1] = 0; Dis2[2] = 0; Dis3[N] = 0;//初始化
while (head < tail) {//广搜
head ++;
for (int i = 0; i < To[Q[head]].size(); i ++) {
if (Dis1[Q[head]] + b < Dis1[To[Q[head]][i]]) {
Dis1[To[Q[head]][i]] = Dis1[Q[head]] + b;
Q[++ tail] = To[Q[head]][i];
}
}
}
int h = 0, t = 0;
for (int i = 0; i < To[2].size(); i ++) {//把第二个点能到的点入队
Q[++ t] = To[2][i];
Dis2[To[2][i]] = e;
}
while (h < t) {//广搜
h ++;
for (int i = 0; i < To[Q[h]].size(); i ++) {
if (Dis2[Q[h]] + e < Dis2[To[Q[h]][i]]) {
Dis2[To[Q[h]][i]] = Dis2[Q[h]] + e;
Q[++ t] = To[Q[h]][i];
}
}
}
int he = 0, ta = 0;
Dis3[N] = 0;
for (int i = 0; i < To[N].size(); i ++) {//把第三个点能到的点入队
Q1[++ ta] = To[N][i];
Dis3[To[N][i]] = p;
}
while (he < ta) {//广搜
he ++;
for (int i = 0; i < To[Q1[he]].size(); i ++) {
if (Dis3[Q1[he]] + p < Dis3[To[Q1[he]][i]]) {
Dis3[To[Q1[he]][i]] = Dis3[Q1[he]] + p;
Q1[++ ta] = To[Q1[he]][i];
}
}
}
Dis1[1] = 0; Dis2[2] = 0; Dis3[N] = 0;
MinAns = Inf;
for (int i = 1; i <= N; i ++)MinAns = min(MinAns,Dis1[i] + Dis2[i] + Dis3[i]);//打个擂台
printf ("%d\n", MinAns);//圆满输出
return 0;
}