• 暑假第二十四测


    题解:

    第一题:二分+贪心;二分距离上限,两端的人能从两端取就从两端取,这样可以为中间的做贡献;

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 10005;
    int a[M], b[M], pos[M], x, n, m;
    bool id[M];
    #define ll long long
    inline int ab(int a, int b){
        if(a > b)return a - b;
        return b - a;
    }
    bool check(ll d){
        memset(id, 0, sizeof(id));
        int lf = 1, rg = m, i;
        for(i = 1; a[i] <= x && i <= n; i++){
            int j;
            for(j = lf; j <= m; j++){
                if(ab(a[i], b[j]) + pos[j] <= d){
                    id[j] = 1;lf = j + 1;break;
                }
            }
            if(j == m + 1)return 0;        
        }
        for(int z = n; z >= i; z--){
            int j;
            for(j = rg; j >= 1; j--){
                if(id[j])continue;
                if(ab(a[z], b[j]) + pos[j] <= d){
                    id[j] = 1;rg = j - 1;break;
                }
            }
            if(!j)return 0;
        }
        return 1;
    }
    int tot;
    int main(){
        
        freopen("keys.in","r",stdin);
        freopen("keys.out","w",stdout);
        int Z = 0, W = 0;
        scanf("%d%d%d", &n, &m, &x);
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]), Z = max(Z, ab(x, a[i]));
        for(int i = 1; i <= m; i++)
            scanf("%d", &b[i]), Z = max(Z, ab(b[i], x));
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + m);
        for(int i = 1; i <= m; i++)pos[i] = ab(b[i], x);
        ll rg;
        if(1LL*(Z + W + b[m] - a[1]) > 2e9)rg = 2e9;
        else rg = Z + W + b[m] - a[1];
        ll lf = 1; 
        int ans;
        while(lf <= rg){
            ll mid = (lf + rg) >> 1;
            if(check(mid))ans = mid, rg = mid - 1;
            else lf = mid + 1;
        }
        printf("%d
    ", ans);
    }
    View Code

    第二题:线段树,我们发现数的先后相对顺序是不变的,所以每次查询序列中最小值,并删除;知道上次的位置,我们优先取他右边小的(如果和左边相同),同一区间的优先选左边;我写了两个小时的第二题,结果少打了一个等号;

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5 + 10;
    #define inf 1e9 + 7
    #define ll long long
    int n, x, a[M], pos[M];
    struct cd{
        int val, id;
        bool operator < (const cd &a)const{
            if(a.val == val)return a.id > id;
            return a.val < val;
            
        }
    }q[M];
    struct Node{
        Node *ls, *rs;
        int sum, v, vin;
        inline void up(){
            sum = ls->sum + rs->sum;
            if(ls->v <= rs->v)vin = ls->vin;
            else vin = rs->vin;
            v = min(ls->v, rs->v);
        }
    }pool[M << 2], *tail = pool, *root;
    Node * build(int l = 1, int r = n){
        Node *nd = ++tail;
        if(l == r) nd->sum = 1, nd->v = a[l], nd->vin = l;
        else {
            int mid = (l + r) >> 1;
            nd->ls = build(l, mid);
            nd->rs = build(mid + 1, r);
            nd->up();
        }
        return nd;
    }
    #define Ls nd->ls, l, mid
    #define Rs nd->rs, mid + 1, r
    
    int query1(int L, int R, Node * nd = root, int l = 1, int r = n){
        if(L <= l && r <= R) return nd->sum;
        else {
            int mid = (l + r) >> 1;
            int ans = 0;
            if(L <= mid)ans += query1(L, R, Ls);
            if(R > mid)ans += query1(L, R, Rs);
            return ans;
        }
        
    }
    int query2(int L, int R, Node * nd = root, int l = 1, int r = n){
        if(L <= l && r <= R) return nd->vin;
        else {
            int mid = (l + r) >> 1;
            int ans1 = 0, ans2 = 0;
            if(L <= mid)ans1 = query2(L, R, Ls);
            if(R > mid)ans2 = query2(L, R, Rs);
            if(a[ans1] <= a[ans2])return ans1;
            else return ans2;
        }
        
    }
    void add(int pos, Node * nd = root, int l = 1, int r = n){
        if(l == r) nd->sum--, nd->v = inf, nd->vin = 0;
        else {
            int mid = (l + r) >> 1;
            if(pos <= mid)add(pos, Ls);
            else add(pos, Rs);
            nd->up();
        }
    }
    
    int main(){
        freopen("cards.in","r",stdin);
        freopen("cards.out","w",stdout);
        
        scanf("%d", &n);
        a[0] = inf;
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        root = build();
        int lst = query2(1, n);
        ll sum = query1(1, lst);
        add(lst);
        for(int i = 2; i <= n; i++){
            int pos1 = query2(lst, n);
            int pos2 = query2(1, lst);
            if(a[pos1] <= a[pos2]){
                sum += 1LL*query1(lst, pos1);
                lst = pos1;
                add(pos1);
            }
            else {
                sum += 1LL*query1(1, pos2) + query1(lst, n);
                lst = pos2;
                add(pos2);
            }    
            
            //printf("%I64d %d %d
    ", sum, a[pos1], a[pos2]);
        }
        printf("%I64d
    ", sum);
    }
    View Code

    第三题:整除分块

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 105;
    #define ll long long
    int n;
    ll k, a[M];
    vector <ll> vec;
    
    bool check(ll d){
        ll ans = 0;
        for(int i = 1; i <= n; i++){
            ll x = (a[i] + d - 1) / d;
            ans += d * x - a[i];
        }
        return ans <= k;
    }
    void split(ll a){
        vec.push_back(a);
        for(ll d = a; d > 0; ){
            ll k = (a + d - 1) / d;
            ll res = (a + k - 1) / k;
            vec.push_back(res);
            d = res - 1;
        }
    }
    
    int main(){
        freopen("bamboo.in","r",stdin);
        freopen("bamboo.out","w",stdout);
        scanf("%d%I64d", &n, &k);
        ll uni = 0;
        for(int i = 1; i <= n; i++){
            scanf("%I64d", &a[i]);
            split(a[i]);
        }
        sort(vec.begin(), vec.end());
        vec.erase( unique(vec.begin(), vec.end()), vec.end());
        vec.push_back( 10000000000000ll );
        int tot = vec.size();
        for(int i = 0; i < tot; i++){
            ll lf = vec[i], rg = vec[i + 1] - 1, ans = 0;
            while(lf <= rg){
                ll mid = (lf + rg) >> 1;
                if(check(mid))ans = mid, lf = mid + 1;
                else rg = mid - 1;
            }    
            uni = max(uni, ans);
        }
        
        
        printf("%I64d
    ", uni);
    }
    View Code
  • 相关阅读:
    加载页面遮挡耗时操作任务页面--第三方开源--AndroidProgressLayout
    【数据库】SQLite学习
    【数据库】MongoDB学习
    【英语】Bingo口语笔记(8)
    【英语】TED视频笔记
    自动关联
    HTML和URL比较
    LR回放测试脚本
    LR录制脚本IE不能打开解决方法
    LR录制测试脚本
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9530002.html
Copyright © 2020-2023  润新知