zoukankan      html  css  js  c++  java
  • 暑假第二十四测

    题解:

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

    #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
  • 相关阅读:
    HDU 2544 最短路
    HDU 3367 Pseudoforest
    USACO 2001 OPEN
    HDU 3371 Connect the Cities
    HDU 1301 Jungle Roads
    HDU 1879 继续畅通工程
    HDU 1233 还是畅通工程
    HDU 1162 Eddy's picture
    HDU 5745 La Vie en rose
    HDU 5744 Keep On Movin
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9530002.html
Copyright © 2011-2022 走看看