SMU Spring 2023 Contest Round 1(MINEYE杯第十六届华中科技大学程序设计邀请赛)

B. Contest Preparation

对n<=m和n==0时特判一下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define inf 0x3f3f3f3f
#define endl '\n'
#define int long long

using namespace std;

const int N = 1e5 + 10, mod = 1e6;
//typedef long long ll;
typedef pair<int,int> PII;
//queue<PII> q1;
//priority_queue <int,vector<int>,greater<int> > q2;
int n,m,t,k;
int ans;
/*
*/
void solve()
{
    cin >> n >> m;
    if( !n ){
        cout << 0 << endl;
        return;
    }
    if(n > 0 && n <= m){
        cout << 2 << endl;
        return ;
    }
    cout << (n * 2 + m - 1) / m << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int Ke_scholar  = 1;
    cin >> Ke_scholar;
    //cin.ignore();
    while(Ke_scholar--)
        solve();
    return 0;
}

D. Difference

参考题解:D Difference (二分 + 单调队列) - Yaqu - 博客园 (cnblogs.com)

由于答案数据范围较大,可以考虑二分答案,要求一个区间的最大最小值,可以采用单调队列,对于每一个要求[l,r]值肯定大于[l-1,r],其max-min也一定大于后一个区间,所以我们可以对于固定的r去找他满足条件的左端点的最右值相加给ans就能得到大于等于k的区间数.

#include  <map>
#include  <set>
#include  <cmath>
#include  <queue>
#include  <stack>
#include  <cstdio>
#include  <vector>
#include  <climits>
#include  <cstring>
#include  <cstdlib>
#include  <iostream>
#include  <algorithm>
#define inf 0x3f3f3f3f
#define endl '\n'
#define int long long

using namespace std;

const int N = 1e5 + 10, mod = 1e9 +7;

//typedef long long ll;
typedef pair<int,int> PII;
//queue<PII> q1;
map<vector<int>, int > mp;
//priority_queue <int,vector<int>,greater<int> > q2;
int n,m,t,k;
/*
*/
int ans;
void solve()
{
    cin >> n >> k;
    vector<int> v(n + 1);
    for(int i = 1;i <= n ;i ++){
        cin >> v[i];
    }
    auto check = [&](int x){
        deque<int> dqmin,dqmax;
        int l = 1, ans = 0;
        for(int i = 1;i <= n;i ++){
            while(!dqmin.empty() && v[dqmin.back()] >= v[i])
                dqmin.pop_back();
            dqmin.push_back(i);
            while(!dqmax.empty() && v[dqmax.back()] <= v[i])
                dqmax.pop_back();
            dqmax.push_back(i);
            while(l <= i && (v[dqmax.front()] - v[dqmin.front()]) * (i - l + 1) >= x){
                if(dqmax.front() == l)
                    dqmax.pop_front();
                if(dqmin.front() == l)
                    dqmin.pop_front();
                l++;
            }
            ans += l - 1;
        }
        return ans >= k;
    };
    int l = 1, r = 1e18,mid;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid))
            l = mid + 1;
        else
            r = mid - 1;
    }
    cout << r << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int Ke_scholar = 1;
    //cin >> Ke_scholar ;
    while(Ke_scholar--)
        solve();
    return 0;
}

 

K. Triangles

对于每一个格子被对角线平分后都能有两个个三角形(开始初始的为1,最后乘2即可),由于数据范围较小,可以直接双for去dp一下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define inf 0x3f3f3f3f
#define endl '\n'
#define int long long

using namespace std;

const int N = 510, mod = 1e6;
//typedef long long ll;
typedef pair<int,int> PII;
//queue<PII> q1;
//priority_queue <int,vector<int>,greater<int> > q2;
int n,m,t,k;
int ans;
int f[N][N];
/*
*/
void solve()
{
    cin >> n;
    for(int i = 0;i < n;i ++){
        int x,y;
        cin >> x >> y;
        f[x][y] = 1;
    }
    for(int i = 0;i < N;i++){
        for(int j = 0; j < N;j++){
            if(f[i][j])
                f[i][j] += f[i - 1][j - 1];
        }
    }
    int ans = 0;
    for(int i = 0;i < N;i ++)
        for(int j = 0;j < N;j ++)
            ans += f[i][j];
    cout << ans * 2 << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int Ke_scholar  = 1;
    //cin >> Ke_scholar;
    //cin.ignore();
    while(Ke_scholar--)
        solve();
    return 0;
}

 

M. XOR Almost Everything

当n为偶数时,一定可以全变为0,当n为奇数时,就将所有数异或起来,若为0,则YES,否则NO.

推倒:

我们可以先通过n次操作把数组全变成相同的一个数,我们下标从i=0取到i=n-1,y就选arr[i]。为什么这样可以使得数组变成相同的一个数?因为这样就相当于使得数组中的每一个数,将除了自己以外的元素都进行了异或运算。这样得到的一个数就是arr[0]^arr[1]^arr[2]……^arr[n-1]。这样每个数都会是相同的,而且这个数就是这个式子得到的结果。

异或运算有两个性质:异或自己就相当于把自己变成0;异或同一个数两次就相当于没异或。

我们再取下标i=0到i=n-1进行操作,y就取arr[0]^arr[1]^arr[2]……^arr[n-1],即现在数组都相同的那个数,这样会使得数组每个元素进行了n-1次运算,当n-1是偶数时,相当于没异或,数组的值不变;当n-1是奇数时,相当于每个元素都异或了一下自身,变成0.

所以当n-1是奇数时,我们必然能把数组变成全是0;而n-1是偶数时,数组的值不会改变,除非arr[0]^arr[1]^arr[2]……^arr[n-1]等于0,这样在一开始把数组变成相同的时候数组就全是0了,其余情况都不能把数组变成0.

原题解:HUSTPC 2022:M、XOR Almost Everything - 掘金 (juejin.cn)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define inf 0x3f3f3f3f
#define endl '\n'
#define int long long

using namespace std;

const int N = 1e5 + 10, mod = 1e6;
//typedef long long ll;
typedef pair<int,int> PII;
//queue<PII> q1;
//priority_queue <int,vector<int>,greater<int> > q2;
int n,m,t,k;
int ans,a[N];
/*
*/
void solve()
{
    cin >> n;
    for(int i = 1;i <= n; i++){
        cin >> a[i];
        ans ^= a[i];
    }
    if(ans == 0 || n % 2 == 0)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int Ke_scholar  = 1;
    //cin >> Ke_scholar;
    //cin.ignore();
    while(Ke_scholar--)
        solve();
    return 0;
}

 

posted @ 2023-05-14 12:47  Ke_scholar  阅读(27)  评论(0编辑  收藏  举报