Codeforces Round #813 (Div. 2)
这一场打得很稀烂QwQ。
开局先看A,开始秒想了一个假掉的做法,WA了3发,以后一定要先证明正确性再写。。。
A写了16分钟。。。
B很快在35分钟的时候秒掉了,C想到了一个暴力做法,但是由于太暴力了,TLE了一发,稍微优化了一下就过掉了(1h19分)。
之后一个小时在推 E 的式子,但一直陷在死循环里,找不到突破口,浅看一下D,感觉好像要写线段树维护区间然后贪心之类的,没有细想,继续推 E 式子到结束。
A Wonderful Permutation
题意
给出一个长为 的排列 ,每一次操作可以交换任意两个位置的数,求使得 最小所需的最小操作次数。
思路
由于 是一个排列,所以使得只要使得 即可。
所以我们判断一下从 到 中是否有大于 的数,是就输出 No
,否则输出 Yes
。
注意多组数据。
const int N = 105; int a[N]; int n, k; void solve() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; int ans = 0; for(int i=1;i<=k;i++) { if(a[i] > k) ans ++; } cout<<ans<<endl; }
B Woeful Permutation
题意
求一个长度为 的排列 ,使得 最大。
思路
对于 为奇数的情况,最后答案为 。
对于 为奇数的情况,最后答案为 。
Proof:
由于 ,所以当 互质的时候最优。
我们发现,一个数和最小(或大)的比它大(或者小)的且与它互质的数求 时,是最优的。
那为什么不去和更大的且与它互质的数求 呢?
设原来的配对为 ,交换成,的话会导致答案偏小。
const int N = 1e5 + 10; int a[N]; void solve() { int n; cin>>n; for(int i=1;i<=n;i++) a[i] = i; if(n % 2 == 1) for(int i=2;i<n;i+=2) swap(a[i],a[i+1]); if(n % 2 == 0) for(int i=1;i<=n;i+=2) swap(a[i],a[i+1]); for(int i=1;i<=n;i++) cout<<a[i]<<' '; cout<<endl; }
C Sort Zero
题意
给出一个长为 的序列 ,每一次操作可以选择一个数 ,将 中的所有等于 的数变为 ,求将序列变成不下降序列所需要的最少操作次数。
思路
我们发现,一旦出现了 ,那么我们就要将下标为 的数都变成 。
Proof:
如果只是将 变为 ,由于原序列中所有数都是大于 的,所以如果 ,就有 。
如此类推, 下标为 的数都一定为 。
所以我们只要用 set 维护 值的个数,如果出现 ,就将 中的所有值标记为 ,答案更新为 中值的个数即可。
const int N = 1e5 + 10; int n; int a[N]; bool st[N]; int main() { int t = 1; cin>>t; while(t--) { scanf("%d",&n); for(int i=0;i<=n;i++) st[i] = 0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); int ans = 0, last = 0; set<int> S; for(int i=1;i<n;i++) { if(st[a[i]]) a[i] = 0; if(st[a[i+1]]) a[i+1] = 0; if(a[i] != 0) S.insert(a[i]); if(a[i] > a[i+1]) { for(int j=last;j<=i;j++) st[a[j]] = 1; last = i; ans = S.size(); } } cout<<ans<<endl; } return 0; }
本文作者:BorisDimitri
本文链接:https://www.cnblogs.com/BorisDimitri/p/16584702.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步