• Codeforces_799


    A.求两个时间比较一下。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,t,k,d;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> t >> k >> d;
        int tt = n/k;
        if(n%k) tt++;
        int sum1 = tt*t;
        int t1 = 0,t2 = d,now = 0;
        while(now < tt)
        {
            if(t1 < t2) t1 += t;
            else    t2 += t;
            now++;
        }
        int sum2 = max(t1,t2);
        if(sum1 > sum2) cout << "YES" << endl;
        else    cout << "NO" << endl;
        return 0;
    }
    View Code

    B.按价格排序,预记录每种颜色的位置,询问的时候保存前一个可行的位置,线性扫即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m,pos[5][200005],ok[200005] = {0};
    struct xx
    {
        int p,a,b;
        friend bool operator <(xx a,xx b)
        {
            return a.p < b.p;
        }
    }a[200005];
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n;
        for(int i = 1;i <= n;i++)   cin >> a[i].p;
        for(int i = 1;i <= n;i++)   cin >> a[i].a;
        for(int i = 1;i <= n;i++)   cin >> a[i].b;
        sort(a+1,a+1+n);
        int cnt[5] = {0};
        for(int i = 1;i <= n;i++)
        {
            int x = a[i].a,y = a[i].b;
            pos[x][++cnt[x]] = i;
            if(x != y)  pos[y][++cnt[y]] = i;
        }
        cin >> m;
        int now[5] = {1,1,1,1,1};
        while(m--)
        {
            int x;
            cin >> x;
            while(ok[pos[x][now[x]]])   now[x]++;
            if(now[x] > cnt[x]) cout << -1 << " ";
            else
            {
                ok[pos[x][now[x]]] = 1;
                cout << a[pos[x][now[x]]].p << " ";
            }
        }
        return 0;
    }
    View Code

    C.分三种情况

    1.两堆各取一个,直接遍历取每堆的符合要求的最大b值。

    2.在A堆取2个。先按p小到大排序,然后从头到尾枚举一个c,二分符合要求的c-p值最后一个的位置,在这一段rmq找最大的b值,更新最大的和。

    3.在B堆取2个,同上。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,c,d;
    int maxdp1[100005][20],maxdp2[100005][20];
    struct xx
    {
        int b,x;
        xx(){};
        xx(int bb,int xx):b(bb),x(xx){};
        friend bool operator <(xx a,xx b)
        {
             return a.x < b.x;
        }
    }a[100005],b[100005];
    
    void rmq_init1(int len)
    {
        for(int i = 1;i <= len;i++) maxdp1[i][0] = a[i].b;
        for(int j = 1;(1<<j) <= len;j++)
        {
            for(int i = 1;i+(1<<j)-1 <= len;i++)
            {
                maxdp1[i][j] = max(maxdp1[i][j-1],maxdp1[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    void rmq_init2(int len)
    {
        for(int i = 1;i <= len;i++) maxdp2[i][0] = b[i].b;
        for(int j = 1;(1<<j) <= len;j++)
        {
            for(int i = 1;i+(1<<j)-1 <= len;i++)
            {
                maxdp2[i][j] = max(maxdp2[i][j-1],maxdp2[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int rmq_max1(int l,int r)
    {
        int k = (int)(log((double)(r-l+1))/log(2.0));
        return max(maxdp1[l][k],maxdp1[r-(1<<k)+1][k]);
    }
    
    int rmq_max2(int l,int r)
    {
        int k = (int)(log((double)(r-l+1))/log(2.0));
        return max(maxdp2[l][k],maxdp2[r-(1<<k)+1][k]);
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> c >> d;
        int cnt1 = 0,cnt2 = 0;
        for(int i = 1;i <= n;i++)
        {
            int x,y;
            string s;
            cin >> x >> y >> s;
            if(s == "C")
            {
                a[++cnt1].b = x;
                a[cnt1].x = y;
            }
            else
            {
                b[++cnt2].b = x;
                b[cnt2].x = y;
            }
        }
        int maxx = 0;
        int pos1 = -1,max1 = 0;
        for(int i = 1;i <= cnt1;i++)
        {
            if(a[i].x <= c && a[i].b > max1)
            {
                pos1 = i;
                max1 = a[i].b;
            }
        }
        int pos2 = -1,max2 = 0;
        for(int i = 1;i <= cnt2;i++)
        {
            if(b[i].x <= d && b[i].b > max2)
            {
                pos2 = i;
                max2 = b[i].b;
            }
        }
        if(pos1 != -1 && pos2 != -1)    maxx = max1+max2;
        sort(a+1,a+1+cnt1);
        sort(b+1,b+1+cnt2);
        rmq_init1(cnt1);
        rmq_init2(cnt2);
        if(cnt1 > 1 && a[1].x+a[2].x <= c)
        {
            for(int i = 1;i <= cnt1;i++)
            {
                if(a[i].x >= c)  break;
                int t = upper_bound(a+1,a+cnt1+1,xx(0,c-a[i].x))-a-1;
                if(t <= i)  break;
                maxx = max(maxx,a[i].b+rmq_max1(i+1,t));
            }
        }
        if(cnt2 > 1 && b[1].x+b[2].x <= d)
        {
            for(int i = 1;i <= cnt2;i++)
            {
                if(b[i].x >= d)  break;
                int t = upper_bound(b+1,b+cnt2+1,xx(0,d-b[i].x))-b-1;
                if(t <= i)  break;
                maxx = max(maxx,b[i].b+rmq_max2(i+1,t));
            }
        }
        cout << maxx << endl;
        return 0;
    }
    View Code

    还有一种方法,直接树状数组维护最大前缀max。

    #include <bits/stdc++.h>
    using namespace std;
    
    int n,c,d,C[100005],D[100005];
    
    inline int lowbit(int x)
    {
        return x & (-x);
    }
    
    void update(int tree[],int pos,int x)
    {
        while(pos <= 100000)
        {
            tree[pos] = max(tree[pos],x);
            pos += lowbit(pos);
        }
    }
    
    int getmax(int tree[],int pos)
    {
        int ans = INT_MIN;
        while(pos > 0)
        {
            ans = max(ans,tree[pos]);
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> c >> d;
        for(int i = 1;i <= 100000;i++)
        {
            C[i] = INT_MIN;
            D[i] = INT_MIN;
        }
        int ans = 0;
        while(n--)
        {
            int b,p,t;
            string s;
            cin >> b >> p >> s;
            if(s == "C")
            {
                if(p > c)   continue;
                t = max(getmax(C,c-p),getmax(D,d));
                update(C,p,b);
            }
            else
            {
                if(p > d)   continue;
                t = max(getmax(C,c),getmax(D,d-p));
                update(D,p,b);
            }
            ans = max(ans,t+b);
        }
        cout << ans << endl;
        return 0;
    }
    View Code

    D.边长指数增长,我们需要的倍数很少,直接爆搜就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    
    int a,b,w,h,n,A[100005],ans;
    
    void dfs(int x,int y,int now,int nowx,int nowy)
    {
        if(nowx >= x && nowy >= y)
        {
            ans = min(ans,now);
            return;
        }
        if(now == n+1)    return;
        if(A[now] == 2)
        {
            while(x > nowx)
            {
                nowx *= 2;
                now++;
            }
            while(y > nowy)
            {
                nowy *= 2;
                now++;
            }
            ans = min(ans,now);
            return;
    
        }
        if(x > nowx)    dfs(x,y,now+1,nowx*A[now+1],nowy);
        if(y > nowy)    dfs(x,y,now+1,nowx,nowy*A[now+1]);
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> a >> b >> w >> h >> n;
        for(int i = 1;i <= n;i++)   cin >> A[i];
        sort(A+1,A+1+n);
        reverse(A+1,A+1+n);
        ans = n+1;
        dfs((a-1)/h+1,(b-1)/w+1,0,1,1);
        dfs((a-1)/w+1,(b-1)/h+1,0,1,1);
        if(ans == n+1)  cout << -1 << endl;
        else    cout << ans << endl;
        return 0;
    }
    View Code

    E.把原数组分为4类,①A、M都不喜欢v0。②A喜欢、M不喜欢。③A不喜欢、M喜欢。④A、M都喜欢。

    我们枚举④中的数量,然后计算剩余②③中最少数量,剩下的数从①②③中小的挑出。

    枚举④的数量从大到小,这样②③个数肯定是递增的,因此就能使用上一次保存②③的个数。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m,k,a[200005];
    int v0[200005],v1[200005],v2[200005],v3[200005];
    long long sum0[200005] = {0},sum1[200005] = {0},sum2[200005] = {0},sum3[200005] = {0};
    bool has1[200005] = {0},has2[200005] = {0};
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m >> k;
        for(int i = 1;i <= n;i++)   cin >> a[i];
        int x;
        cin >> x;
        while(x--)
        {
            int xx;
            cin >> xx;
            has1[xx] = 1;
        }
        cin >> x;
        while(x--)
        {
            int xx;
            cin >> xx;
            has2[xx] = 1;
        }
        int cnt0 = 0,cnt1 = 0,cnt2 = 0,cnt3 = 0;
        for(int i = 1;i <= n;i++)
        {
            if(has1[i] && has2[i])  v3[++cnt3] = a[i];
            else if(has1[i])    v1[++cnt1] = a[i];
            else if(has2[i])    v2[++cnt2] = a[i];
            else    v0[++cnt0] = a[i];
        }
        sort(v0+1,v0+1+cnt0);
        sort(v1+1,v1+1+cnt1);
        sort(v2+1,v2+1+cnt2);
        sort(v3+1,v3+1+cnt3);
        for(int i = 1;i <= cnt0;i++)    sum0[i] = sum0[i-1]+v0[i];
        for(int i = 1;i <= cnt1;i++)    sum1[i] = sum1[i-1]+v1[i];
        for(int i = 1;i <= cnt2;i++)    sum2[i] = sum2[i-1]+v2[i];
        for(int i = 1;i <= cnt3;i++)    sum3[i] = sum3[i-1]+v3[i];
        long long ans = 1e18;
        int t1 = 0,t2 = 0;
        for(int i = min(cnt3,m);i >= 0;i--)
        {
            t1 = max(t1,k-i),t2 = max(t2,k-i);
            if(t1+t2+i > m || t1 > cnt1 || t2 > cnt2)   break;
            if(cnt0+cnt1+cnt2+i < m)    break;
            int t0 = 0;
            while(t0+t1+t2+i < m)
            {
                int t = m-t1-t2-i;
                if(cnt0 >= t && (t1 == cnt1 || v0[t] <= v1[t1+1]) && (t2 == cnt2 || v0[t] <= v2[t2+1])) {t0 = t;break;}
                else if(t1 < cnt1 && (t2 == cnt2 || v1[t1+1] <= v2[t2+1]))  t1++;
                else    t2++;
            }
            ans = min(ans,sum0[t0]+sum1[t1]+sum2[t2]+sum3[i]);
        }
        if(ans == 1e18) cout << -1 << endl;
        else    cout << ans << endl;
        return 0;
    }
    View Code

  • 相关阅读:
    oracle 更改账户名密码
    mongodb 分片副本集搭建
    爬虫目录
    centos MySQL安装与卸载
    ANACONDA 安装
    chrome 安装
    linux pycharm 安装 idea
    linux 基本命令
    高数18讲 之极限与连续
    高数18讲 之基础知识
  • 原文地址:https://www.cnblogs.com/zhurb/p/6847893.html
Copyright © 2020-2023  润新知