zoukankan      html  css  js  c++  java
  • 18.8.24 考试总结

    一开始我这道题竟然以为是最小费用最大流...怪我错误的预估了网络流的复杂度...。

    然后把1mb记成了1e7...我已经被自己蠢死了cnm

    这道题就是一个二分 + 贪心   先把所有的人和所有的钥匙从左到右排一边序

    二分最大的限制时间是多少 然后就O(n)check是否合法

    现在的问题就是如何check  那么对于每一把钥匙c 两个人a b

    如果a拿钥匙合法 b拿钥匙则不一定合法 会更劣

    所以从左往右扫的时候如果这个人能拿这个钥匙就拿 不能拿钥匙就换向右的下一把 看最终合法的人数是否等于n就可以了

    代码

    #include <bits/stdc++.h>
    #define oo 1e9
    using namespace std;
    const int N = 1e5 + 5;
    int n,m,ans = oo,k,b[N],a[N];
    bool check(int lim) {
        
        int key = 1,p = 1;
        int num = 0;
        while(key <= m) {
            if(abs(k - b[key]) + abs(a[p] - b[key]) <= lim)
              p ++,num ++;
            if(num == n) break;
            key ++;
        }
        return num == n;
    }
    void solve( ) {
        
        int l = 1,r = oo;
        ans = oo;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(check(mid)) ans = mid,r = mid - 1;
            else l = mid + 1;
        }
    }
    int main( ) {
        
        freopen("keys.in","r",stdin);
        freopen("keys.out","w",stdout);
        scanf("%d%d%d",& n,& m,& k);
        for(int i = 1;i <= n;i ++) scanf("%d",& a[i]);
        for(int i = 1;i <= m;i ++) scanf("%d",& b[i]);
        sort(a + 1,a + n + 1);
        sort(b + 1,b + m + 1);
        solve( );
        printf("%d",ans);
    }

    这道题就是一道裸的数据结构吧我觉得...

    考试的时候还是调了一段时间

    就线段树各种操作都搞一搞就可以了..。

    我的query比较奇怪 就是乱搞搞某个区间的size 以及最小值的pos 

    代码

    #include <bits/stdc++.h>
    #define oo 1e9
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 5;
    int n,a[N],nex[N],las[N],now;
    ll ans;
    struct node {
        
        int val,size,pos;
    }f[4 * N];
    inline int read( ) {
        
        int ans = 0,t = 1;
        char x; x = getchar( );
        while(x < '0' || x > '9') {
            if(x == '-') t = -1;
            x = getchar( );
        }
        while(x >= '0' && x <= '9') {
            ans = ans * 10 + x - '0';
            x = getchar( );
        }
        return ans * t;
    }
    void update(int o) {
        
        f[o].val = min(f[2 * o].val,f[2 * o + 1].val);
        f[o].size = f[2 * o].size + f[2 * o + 1].size;
        f[o].pos = f[2 * o].val <= f[2 * o + 1].val ? f[2 * o].pos : f[2 * o + 1].pos;
    }
    void build(int o,int l,int r) {
        
        if(l == r) {
            f[o].val = a[l];
            f[o].pos = l;
            f[o].size = 1;
            return ;
        }
        int mid = (l + r) >> 1;
        build(2 * o,l,mid);
        build(2 * o + 1,mid + 1,r);
        update(o);
    }
    void modify(int o,int l,int r,int p) {
        
        if(l == r) {
            f[o].val = oo;
            f[o].pos = 0;
            f[o].size = 0;
            return ;
        }
        int mid = (l + r) >> 1;
        if(p <= mid) modify(2 * o,l,mid,p);
        else modify(2 * o + 1,mid + 1,r,p);
        update(o);
    }
    node query(int o,int l,int r,int L,int R) {
        
        if(l >= L && r <= R) {
            return f[o];
        }
        int mid = (l + r) >> 1;
        node ans; ans.val = oo,ans.pos = 0,ans.size = 0;
        if(L <= mid) {
            node ll;  ll = query(2 * o,l,mid,L,R);
            ans.val = min(ans.val,ll.val);
            ans.pos = ll.pos; ans.size += ll.size;
        }
        if(mid < R) {
            node rr;  rr = query(2 * o + 1,mid + 1,r,L,R);
            if(ans.val > rr.val) ans.pos = rr.pos;
            ans.val = min(ans.val,rr.val);
            ans.size += rr.size;
        }
        return ans;
    }
    void solve( ) {
        
        now = 1;
        for(int i = 1;i <= n;i ++) {
            nex[i] = i + 1;
            if(i == n) nex[i] = 1;
            las[i] = i - 1;
            if(i == 1) las[i] = n;
        }
        int p;
        for(int i = 1;i <= n;i ++) {
            node np,qp;
            qp = query(1,1,n,now,n);
            if(now > 1){
                np = query(1,1,n,1,now - 1);
            }
            else np.val = oo,np.size = 0;
            node ss = query(1,1,n,1,now);
            if(qp.val > np.val) {
                p = np.pos;
                node s = query(1,1,n,1,np.pos);
                ans += (ll)f[1].size - (ll)(ss.size - s.size - 1);
            }
            else {
                p = qp.pos;
                node s = query(1,1,n,1,qp.pos);
                ans += (ll)(s.size - ss.size + 1);
            }
            modify(1,1,n,p); int pre = las[p];
            now = nex[p]; nex[pre] = now;
            las[now] = pre;
        }
    }
    int main( ) {
        
        freopen("cards.in","r",stdin);
        freopen("cards.out","w",stdout);
        n = read( );
        for(int i = 1;i <= n;i ++)
            a[i] = read( );
        build(1,1,n);
        solve( );
        printf("%I64d",ans);
    }

    第三题是一道整除分块的题

    由题目可得 ∑(ai / d)上取整 * d - ai ≤ k 

    昨天idy给我们讲了如何推出满足a / d 下取整= x的最大d

    同样的 今天这道题是求得满足a / d上取整 = 某个值的最小d

    所以就对d进行分块 讲a / d相等的分为一个快 因为这样子同一个块内d是满足二分性的

    但是因为有多个a  所以就对所有小断点都分一下块

    就像这样

    可以进行二分来找最大的满足条件的d 因为将式子里的d提出来后 同一个块内的∑(ai / d)上取整是相同的

    所以这个东西就变成了一个关于d的一次函数 就可以二分 二分朴素做法是O(n)判断 这道题是可以的 

    但是有更优秀的O(1)判断 对于同一个块内 d的增减只会改变系数的个数 而系数是不变的 所以可以直接加上delta d * 系数

    这样二分check时 复杂度就从n变成了1 (然而标程写的是O(n)check)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 111;
    int n;
    long long k;
    vector<long long> vc;
    long long aa[N];
    inline long long read( ) {
        
        long long ans = 0,t = 1;
        char x; x = getchar( );
        while(x < '0' || x > '9') {
            if(x == '-') t = -1;
            x = getchar( );
        }
        while(x >= '0' && x <= '9') {
            ans = ans * 10 + x - '0';
            x = getchar( );
        }
        return ans * t;
    }
    void split( long long a, vector<long long> &vc ) {
        vc.push_back(a);
        for(long long d = a;d;) {
            long long dd = (a + d - 1) / d;
            long long k = (a + dd - 1) / dd;
            vc.push_back(k);
            d = k - 1;
        }
    }
    bool check( long long d ) {
        long long sum = 0;
        for( int i = 1; i <= n; i++ ) {
            sum += (aa[i] + d - 1) / d * d - aa[i];
        }
        return sum <= k;
    }
    int main() {
        freopen("bamboo.in", "r", stdin);
        freopen("bamboo.out", "w", stdout);
        scanf("%d%I64d", &n, &k );
        for( int i = 1; i <= n; i++ ) {
            aa[i] = read( );
            split(aa[i],vc);
        }
        sort( vc.begin(), vc.end() );
        vc.erase(unique(vc.begin(),vc.end()),vc.end());
        vc.push_back( 10000000000000ll );
        long long ans = 1;
        for( int t = 0; t + 1 < (int)vc.size(); t++ ) {
            long long lf = vc[t];
            long long rg = vc[t+1] - 1;
            if( check(lf) == false ) continue;
            while( lf < rg ) {
                long long mid = (lf + rg + 1) >> 1;
                if( check(mid) )
                    lf = mid;
                else
                    rg = mid - 1;
            }
            ans = max( ans, lf );
        }
        printf( "%I64d
    ", ans );
    }
  • 相关阅读:
    剑桥雅思写作高分范文ESSAY96
    剑桥雅思写作高分范文ESSAY95
    剑桥雅思写作高分范文ESSAY94
    剑桥雅思写作高分范文ESSAY93
    剑桥雅思写作高分范文ESSAY92
    剑桥雅思写作高分范文ESSAY91
    PHP 伪静态规则写法RewriteRule-htaccess详细语法使用
    php页面静态常用函数
    正则函数[原则,能用字符串函数解决不用正则,速度问题]s
    使用xshell文件传输
  • 原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9534485.html
Copyright © 2011-2022 走看看