CF #776 Div.3
A Deletions of Two Adjacent Letters(思维)
Description:
给定一个字符串s和字符c 每次可以从字符串s中消除相邻的两个位置的字符 问是否能通过消除来得到字符c
Method:
枚举字符串中每一个c 若前后都为偶数的话 能
Code:
void solve()
{
string s;
char c;
cin >> s >> c;
for(int i = 0; i < s.size(); i++)
{
if(s[i] != c) continue;
if(i % 2 == 0 && (s.size() - 1 - i) % 2 == 0)
{ puts("YES"); f = 1; break;}
}
if(f == 0) puts("NO");
}
B DIV + MOD(分类讨论 + 贪心)
Description:
定义一个函数f(x) = x / a + x mod a
给定上下界l r 整数a
求在[l, r]内的f(x) Max
Method:
分类讨论 要么让/尽量大 要么让%尽量大
前一种是 r / a + r % a;
后一种是选接近r的a的倍数 - 1
t = r / a * a - 1;(t >= l才成立)
Code:
void solve()
{
int l, r, a;
cin >> l >> r >> a;
int res = r / a + r % a;
int t = r / a * a - 1;
if(t >= l) res = max(res, t / a + t % a);
cout << res << '\n';
}
C Weight of the System of Nested Segments(排序 + 构造)
Description:
给定m个点和其值 根据要求选择点构成n个数对
要求
- 必须构成n个数对
- 必须是层层包含的(内层的数对被外层的数对的坐标区间包含)
- 保证数对的值之和 取Min
依次输出数对的下标 数对的下标由输入顺序决定
Method:
用结构体存储每一个点的 坐标 值 下标
对值排序 小到大 那么最理想的情况就是找到前2 n个数字 组成数对 但由于要求包含 现实情况并非理想
呸 是个锤子 事实就是那么理想
直接找出2 * n个值最小的数
然后删去多余的点 再对位置排序 每次选最外面的两个
Code:
struct node
{
int val, pos, id;
};
int cmp1(node a, node b)
{
return a.val < b.val;
}
int cmp2(node a, node b)
{
return a.pos < b.pos;
}
void solve()
{
int n, m;
cin >> n >> m;
vector<node> q(m);
for(int i = 0; i < m; i++)
{
cin >> q[i].pos >> q[i].val;
q[i].id = i + 1;
}
sort(q.begin(), q.end(), cmp1);
int sum = 0;
for(int i = 0; i < m; i++)
{
if(i < 2 * n) sum += q[i].val;
else q.pop_back();
}
sort(q.begin(), q.end(), cmp2);
cout << sum << '\n';
for(int i = 0; i < n; i++)
cout << q[i].id << " " << q[2 * n - 1 - i].id << '\n';
}
D Twist the Permutation()
Description:
给定序列 是由1~n的序列经过操作形成的
op:将从1开始长度为k的序列循环右移x次
请问是怎么通过操作还原的 输出数组k
表示操作每段长度循环右移的次数
Method:
既然是通过循环右移得来 那么我们可以通过循环左移将其移动回去
倒序模拟还原 因为当 j 确定了之后 下一次操作只会影响到前 j - 1 位
枚举j 找到 j 目前存在的位置 将其整段循环左移至j 回到原位 先更改备份数组 然后再还原回去
debug 打印数组发现 当j减到0的时候 他应该是要回到i的 手动为他还原一下就好了
Code:
int q[2010], res[2010], backup[2010];
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> q[i];
for(int i = n; i >= 1; i--) //枚举数字
{
int idx;
for(int j = 1; j <= n; j++) //枚举出当前需要的i的坐标j
idx = q[j] == i ? j : idx;
res[i] = idx % i; //若 已经在本位上 左移0次
for(int j = 1; j <= i; j++)
if((j - res[i] + i) % i == 0) backup[i] = q[j];
//当被移动到0的时候 通过打印数组debug
else backup[(j - res[i] + i) % i] = q[j]; //长度为i的数组循环一位res[i]次
for(int j = 1; j <= i; j++) //备份还原
q[j] = backup[j];
}
for(int i = 1; i <= n; i++)
cout << res[i] << ' ';
cout << '\n';
}
E Rescheduling the Exam()
Description:
Method:
Code: