Codeforces Round 932 (Div. 2)题解(c、d)

Codeforces Round 932 (Div. 2)

C. Messenger in MAC

题目大意

给定一些aibi,选出尽量多的aibi,使得i=1kapi+i=1k1|bpibpi+1|小于给定的l

题目解析

由于题目没有要求{p}是升序排列的序列,因此我们可以改变ai的顺序。注意到ai的值是无法改变的,i=1k1|bpibpi+1|可以通过改变 bi的顺序改变大小。考虑到贪心,最终一定有bpibpi+1

(假设有 a<b<c,一定是 |ab|+|bc|<|ac|+|bc|

因此先按照b的大小对序列 {ab}进行排序,假设选择了从lr的若干对 ab,一定有 i=1k1|bpibpi+1|=brbl(已经对 b排序了,所以一定是升序排列),接着只要处理i=1kapi即可。

我们不妨考虑双指针的写法进行 O(N2)遍历:固定住最左边的数字后,不停的向右移动指针。令res表示当前的i=1kapi+i=1k1|bpibpi+1|,每次向右移动指针时,resbr+br+1,同时通过优先队列,将所有的ai从大到小的排序,每当答案过大时,就从优先队列中排除若干个ai,直到小于l为止。

#include<bits/stdc++.h> typedef long long ll; using namespace std; const int N = 2007; ll a[N] , b[N] ; void solve() { int n,L; scanf("%d%d",&n,&L); vector<pair<ll,ll> >c(n); for(auto &[x,y]:c) { scanf("%lld%lld",&y,&x); } ll ans = 0; // 根据第二元素为关键字 sort(c.begin(),c.end()); for(int i = 1 ; i <= n ; i++) { b[i] = c[i-1].first; a[i] = c[i-1].second; } for(int l = 1 ; l <= n ; l++) { priority_queue<ll> q; ll sum =0; for(int r = l ; r <= n ; r++) { q.push(a[r]); sum += a[r]; while(sum + b[r] - b[l] > L && q.size() ) { sum -= q.top(); q.pop(); } ans = max(ans,(ll)q.size()); } } printf("%lld\n",ans); } int main() { int tc; cin >> tc; while(tc--) solve(); }

D. Exam in MAC

题目大意

给定一个大小为 n 的集合 s 和一些奇怪的整数 c。对于这个集合,需要计算整数对 (x,y) 的数量,使得 0 ≤ x ≤ y ≤ cx+y 不包含在集合 s 中,且 y-x 也不包含在集合 s 中。

题目解析

考虑鸽笼原理。我们记"x+ys"为条件一,"yxs"为条件二,若需要两者都不满足,可以写为:

sumcondition1condition2+(condition1&condition2)

即减去满足条件一的的数量、满足条件二的数量后,再加上满足两个条件的数量。

  • 对于条件一:假设i=x+y,is,则满足此条件的x,yi/2+1对。
  • 对于条件二:假设i=xy,is,则需要注意,xc,y0,一共有 ci+1(x,y)满足此条件。
  • 对于条件一和条件二同时满足:假设 x+y=i,yx=j,有 2y=i+j(ji),且i+j是偶数,因此必须是奇数加奇数、偶数加偶数的形式。假设s中有n个奇数,则只选择奇数作为i,j会产生(n+1)n2个符合条件的(x,y)(对于s中第一个奇数,有n个数字和其能匹配;对于第二个奇数,由于大于第一个奇数,所以只能和第二个及以后的数字匹配),偶数同理。
#include<bits/stdc++.h> using namespace std; using ll = long long; void solve() { ll n,c; scanf("%lld%lld",&n,&c); vector<ll>a(n); for(auto &i:a) scanf("%lld",&i); ll ans = (c+1)*(c+2)/2 ,cnt = 0; for(auto i:a) { ans -= (c-i+1); // x-y=i ans -= (i/2+1);// x+y=i if(i%2) cnt++; } auto C = [&](ll n) {// 从n里面选2个 return (n+1)*n/2; }; ans += C(cnt) + C(n-cnt); printf("%lld\n",ans); } int main() { #ifdef jhon freopen("std.in","r",stdin); #endif int tc; cin >> tc; while(tc--) solve(); }

__EOF__

本文作者seekerzhz
本文链接https://www.cnblogs.com/zhaohanzheng/p/18145873.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   seekerHeron  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2022-04-19 石子游戏 II
点击右上角即可分享
微信分享提示