(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(4)

1003 Simple Set Problem

双指针的思想,双端队列

先从小到大排个序

一个一个放到双端队列里,一边放一边维护集合个数为k个

利用滑动窗口,当滑动窗口中集合个数为k时,只需算出滑动窗口最后一个数减去第一个数,然后每次取min就行了

AC代码: 

#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
typedef pairPII;
const int N=1e6+10;
typedef pairPII;
typedef long long ll;
int k,c;
int cnt[N];
void solve()
{
    cin>>k;
    int n=0;
    vectorans;
    for(int i=0;i>c;
        n+=c;
        while(c--){
            int x;
            cin>>x;
            ans.push_back({x,i});
        }
    }
    sort(ans.begin(),ans.end());
    int sum=0;
    int res=2e9;
    dequeq;
    for(int i=0;i1){
            cnt[ans[q.front()].second]--;
            q.pop_front();
        }
        res=min(res,ans[q.back()].first-ans[q.front()].first);
    }
    cout<>t;
    while(t--)
    solve();
    return 0;
}

1006 PSO 

两两组合

期望=所有组合的边数/组合数

组合数为中心节点与其它n-1个节点组合+在其它n-1个节点中选2个的组合(cnt)

所有组合的边数为n-1+2*cnt

当n大于2时,最大值均为2

另外,当n为2时,还需要特判,最大值为1

AC代码: 

#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
//typedef pairPII;
typedef long long ll;
ll n;
ll C2(ll x){
    return x*(x-1)/2;
}
void solve()
{
    cin>>n;
    double res=((double)2*C2(n-1)+n-1)/(C2(n-1)+n-1);
    printf("%.9lf ",res);
    if(n==2) printf("%.9lf\n",1.0);
    else printf("%.9lf\n",2.0);
}
int main()
{
//    ios::sync_with_stdio(false);
//    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--)
    solve();
    return 0;
}

1010 Kong Ming Qi 

n*m和m*n是等价的,所以统一换成n小m大 

当n为1时,答案明显为(m+1)/2

然后由一个基本图形(图1),可以吃掉连续三个棋子(如图4)

(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(4)_第1张图片 

 

所以当n不是1时,我们都可以一直消掉3列

所以我们可以打表在一个范围里,当n和m很大时,都可以通过消掉3列,消掉3行来使得其落在打表范围里

当n等于5并且m等于5时,可以这么消

(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(4)_第2张图片 

当n大于等于6,并且m大于等于6时,更加可以消3行3列

但是当n为4,m为5时,就只能消掉3列,行就不行了,所以当n和m都大于等于5时,才消3行3列,所以我们打表打到4*4

(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(4)_第3张图片 

AC代码: 

#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
int ans[4][4]=
{
    {1,1,2,2},
    {1,1,2,1},
    {2,2,2,2},
    {2,1,2,1}
};
void solve()
{
    int n,m;
    cin>>n>>m;
    if(n>m) swap(n,m);
    if(n==1){
        cout<<(m+1)/2;
        return;
    }
    while(n>=5) n-=3;
    while(m>=5) m-=3;
    cout<>t;
    while(t--)
    solve();
    return 0;
}

1012 a-b Problem

对于每一个ai,bi,求它们的和,然后从大到小排序,依次取

原因在于自己取了其中一个,对方没有取另一个,那么自己比对方就多了两者之和

AC代码:

#include
#include
#include
#include
#include
#include
#define endl '\n'
//#define int long long
using namespace std;
const int N=1e5+10;
//typedef pairPII;
typedef long long ll;
ll n;
struct node{
    ll a;
    ll b;
    ll sum;
    bool operator<(const node &W)const{
        return sum>W.sum;
    }
}ans[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>ans[i].a>>ans[i].b;
        ans[i].sum=ans[i].a+ans[i].b;
    }
    sort(ans+1,ans+1+n);
    ll sum1=0,sum2=0;
    for(int i=1;i<=n;i++){
        if(i%2==1) sum1+=ans[i].a;
        else sum2+=ans[i].b;
    }
    cout<>t;
    while(t--)
    solve();
    return 0;
}

你可能感兴趣的:(2023杭电多校,算法,c++)