文章目录
前言
2021南京,号称今年最卷的icpc区域赛。
上周末训练赛和队友打了一下,争取多补几道题。
比赛链接:https://codeforces.com/gym/103470
题目一览
签到题:A,C,M,H
铜牌题:D
银牌题:J
金牌题:I ,G
我不能做的题:B,F,K,L
本场差不多是4.5题铜,5.5题银,7题金(4题铜5题银的概率不大,约等于5铜,6银,7金)
A.Oops, It’s Yesterday Twice More(签到)
题意
不知道,队友写的
思路
不知道,队友写的
M. Windblume Festival(签到)
题意
给一个长度为n整数序列 a [ ] a[] a[] , 每次操作可以选择两个下标 i , j i,j i,j ( i < j i < j i<j,环形) , 移除 a j a_j aj , 并且令 a i = a i − a j a_i = a_i - a_j ai=ai−aj 。
最后会剩下一个元素,要求最大化这个元素。 ( 1 < = n < = 1 0 6 1<=n<=10^6 1<=n<=106)
input
5
4
1 -3 2 -4
11
91 66 73 71 32 83 72 79 84 33 93
12
91 66 73 71 32 83 72 79 84 33 33 93
13
91 66 73 71 32 83 72 79 84 33 33 33 93
1
0
output
10
713
746
779
0
Note
For the first sample test case follow the strategy shown below, where the underlined integers are the integers held by the players selected in each turn.
{1–,−3,2,−4}(select x=4) →→ {−3,2,−5} (select x=2x) →→ {−3,7} (select x=2) →→ {10}}.
思路
这是一个环形的结构,所以我们可以“自行地”决定一个数的贡献是正的还是负的。并且一定会有一个正的贡献,并且n>1时必定有一个负的贡献。
所以,答案就是 a n s = m a x − m i n + s u m ( r e s ) ans = max - min + sum(res) ans=max−min+sum(res)。
C. Klee in Solitary Confinement(思维+前缀和)
题意
给一个长度为n整数序列 a [ ] a[] a[] , 给一个正整数 k k k 。
可以选择一段区间 [ l , r ] [l,r] [l,r] , 将其中所以元素加 k k k 。
要求最大化出现次数最多的数的数量。
( 1 ≤ n ≤ 1 0 6 , − 1 0 6 ≤ k ≤ 1 0 6 , − 1 0 6 ≤ a i ≤ 1 0 6 ) (1≤n≤10^6, −10^6≤k≤10^6 ,−10^6≤a_i≤10^6) (1≤n≤106,−106≤k≤106,−106≤ai≤106)
Examples
input
5 2
2 2 4 4 4
output
5
input
7 1
3 2 3 2 2 2 3
output
6
input
7 1
2 3 2 3 2 3 3
output
5
input
9 -100
-1 -2 1 2 -1 -2 1 -2 1
output
3
思路
不难发现,对于每个数字 i i i,我们只需要考虑 i i i 和 i + k i+k i+k 的相对位置关系,可以忽略其他所有的数字。
所以我们可以遍历一遍数组,用 v e c t o r vector vector将每个 i i i 和 i + k i+k i+k分在一个组里并保留相对位置。
对每个组,令 a i = 1 a_i = 1 ai=1 , a i + k = − 1 a_i+_k = -1 ai+k=−1,目标就是最大化区间找出区间和最大的区间 [ l , r ] [l,r] [l,r]。
意思就是对于区间 [ l , r ] [l,r] [l,r] , 我们能令最多的 a i a_i ai变成 a i + k a_i+_k ai+k 的同时,令最少的 a i + k a_i+_k ai+k被改变。
实现上,我们维护一个前缀和 sum[i] 和最小前缀和 sum_min[i] 即可。
代码
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
#define int long long
const int BASE=1e6;
const int MAXN=4e6+20;
int n,k,a,sum[MAXN/4],minn,maxn,summin[MAXN/4],cnt[MAXN],flag,ans,tot;
vector<int> s[MAXN];
void solve(int num) {
tot=s[num].size();
if(tot==0) return;
ans=max(ans,cnt[num]+s[num][0]);
sum[1]=s[num][0];
summin[1]=min(sum[0],sum[1]);
for(int i=2;i<=tot;++i) {
sum[i]=sum[i-1]+s[num][i-1];
summin[i]=min(summin[i-1],sum[i]);
ans=max(ans,sum[i]-summin[i-1]+cnt[num]);
//cout<<i<<" "<<sum[i]<<" "<<summin[i-1]<<'\n';
}
for(int i=1;i<=tot;++i) sum[i]=summin[i]=0;
}
signed main()
{
scanf("%lld%lld",&n,&k);
flag=1;
if(k<0) flag=-1,k=-k;
minn=5e6,maxn=-1;
for(int i=1;i<=n;++i) {
scanf("%lld",&a);
a=a*flag+BASE;
minn=min(minn,a);
maxn=max(maxn,a);
++cnt[a];
ans=max(ans,cnt[a]);
s[a].push_back(-1);
s[a+k].push_back(1);
}
if(k!=0)
{
for(int i=minn+k;i<=maxn;++i)
solve(i);
}
cout<<ans;
return 0;
}
H. Crystalfly(树形dp)
题意
给一棵 n n n 个点带点权的树 ( 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1≤n≤105 , 1 ≤ a i ≤ 1 0 9 1≤a_i≤10^9 1≤ai≤109)
从 1 号点出发,每个点的点权可以吃一次,要求最大化吃到的点权和。
每个点还有另一个值 t i t_i ti , 当你走到这个点的相邻节点时,这个点会被" d i s t u r b disturb disturb " , t i t_i ti 开始倒计时,如果在倒计时结束前还没能吃到这个点,那这个点的点权会消失(注意,可以经过,只是吃不到点权)。 其中 1 < = t i < = 3 1<=t_i<=3 1<=ti<=3。
输入多组样例,每组样例第一行 n n n,第二行点权,第三行 t i t_i ti,然后是树边
input
2
5
1 10 100 1000 10000
1 2 1 1 1
1 2
1 3
2 4
2 5
5
1 10 100 1000 10000
1 3 1 1 1
1 2
1 3
2 4
2 5
output
10101
10111
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACto4wLB-1649091209048)(C:\Users\xi2001\AppData\Roaming\Typora\typora-user-images\image-20220404114835027.png)]](https://i-blog.csdnimg.cn/blog_migrate/3c479d6e2bc22895108bbb9edf99d319.png)
思路

分享2021南京icpc区域赛解题笔记,涵盖签到题、铜牌题至金牌题的思路解析,包括前缀和优化、树形dp、数论技巧等,助你理解比赛难题
最低0.47元/天 解锁文章
1449

被折叠的 条评论
为什么被折叠?



