点这里

A题 构造数列

这题么是很简单的,签到题,但是我好像想复杂了,罚时太长了,直接取出每一位不为零的数即可。

比赛时的做法

属实是个铁憨憨

#include <iostream>
#include <cstring>
#include <algorithm>
#include<vector>

using namespace std;

int n;
int a[28]={10000,9000,8000,7000,6000,5000,4000,3000,2000,1000,900,800,700,600,500,400,300,200,100,
         90,80,70,60,50,40,30,20,10};

int main() {
    int T;
    cin >> T;
    while (T--) {
        vector<int> num;
        cin >> n;
        for (int i = 0; i <28 ; i++) {
            if (a[i] <= n) {
                n -= a[i];
                num.push_back(a[i]);
            }
            if (n < 10 && n > 0) {
                num.push_back(n);
                break;
            }
        }
        cout << num.size() << endl;
        for (auto i: num)cout << i << ' ';
        cout << endl;
    }
    return 0;
}
快的做法
#include <iostream>
#include <cstring>
#include <algorithm>
#include<vector>

using namespace std;

const int N = 10010;

int main()
{
    int T;
    cin>>T;
    while(T--){
        string str;
        cin>>str;
        vector<int> s;
        for(int i=str.size()-1,j=1;i>=0;i--,j*=10){
            if(str[i]!='0')
            s.push_back((str[i]-'0')*j);
        }
        cout<<s.size()<<endl;
        for(auto i:s)cout<<i<<' ';
        cout<<endl;
    }
    return 0;
}

B题 浇花

本题的根本就是差分,但是因为数据的原因,暴力也可以过。

暴力做法

#include <iostream>
#include <cstring>
#include <algorithm>
#include<map>
#define f first
#define s second

using namespace std;

const int N = 100010;

int n,m;
map<int,int> mp;
int a[N];

int main() {
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int l, r;
        cin >> l >> r;
        if (l == r)a[l]++;
        else for(int j=l;j<=r;j++)a[j]++;
    }
    //for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<endl;
    for(int i=1;i<=n;i++){
        if(a[i]==0||a[i]>1){
            cout<<i<<' '<<a[i]<<endl;
            return 0;
        }
    }
    cout << "OK" << endl;
}

用差分来做

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010;

int n,m;
int b[N];

int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int l,r;
        cin>>l>>r;
        b[l]++,b[r+1]--;
    }
    for(int i=1;i<=n;i++){
        b[i]+=b[i-1];
        if(b[i]>1||b[i]==0){
            cout<<i<<' '<<b[i]<<endl;
            return 0;
        }
    }
    puts("OK");
    return 0;
}

C题 构造新矩阵

这个题其实考察的是二分,给一个m乘以n的矩阵,让你输出一个尽可能大的值L使得最多选n-1行构造一个新矩阵,让这个新矩阵每一列至少有一个元素大于等与于L,因为L这个答案具有二段性,小于L的肯定成立,而大于L的肯定不成立,所以二分这个答案,然后我们就全部遍历一下这个矩阵,看看每一列是不是至少有一个数大于等于L,但只能取n-1行,所以我们还要再开一个数组取判断有没有至少两行的值大于等于L重复,只要有一个重复的就可以取n-1行否则就不行。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 100010;

vector<int> g[N];
int n, m;
bool st[N];

bool check(int x) {
    memset(st, false, sizeof st);
    bool same = false;
    for (int i = 0; i < n; i++) {
        bool success = false;
        for (int j = 0; j < m; j++) {
            if (g[j][i] >= x) {
                success = true;
                if (st[j])same = true;
                st[j] = true;
            }
        }
        if (!success)return false;
    }
    return same;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> m >> n;
        for (int i = 0; i < m; i++) {
            g[i].resize(n);
            for (int j = 0; j < n; j++)
                cin >> g[i][j];
        }

        int l = 1, r = 1e9;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (check(mid))l = mid;
            else r = mid - 1;
        }
        cout << l << endl;
    }
    return 0;
}