• 小R的调度


    【问题描述】
    小 R 是一名 OIer,她刚刚学习了逆序对的相关知识:对于一个长度为 n的
    序列 A,其逆序对数定义为满足 i < j 且 A[i] > A[j]的(i, j)对数。
    现在小 R 有一个长度为 n的 01序列 A,小 R每次可以交换 当前 A[i]与 A[j]
    的值,并需要付出 c[i] + c[j]的代价。在若干轮(可以为空)交换后,小 R的得
    分为最终 A序列的逆序对数减去她在交换中付出的代价之和。
    小 R 想让最后的得分尽量大,你能帮帮她吗?
    【输入】
    第一行为一个正整数 n。
    第二行为一个长度为 n的字符串,表示 01序列 A。
    第三行为 n个整数 c[i],表示交换的代价参数。
    【输出】
    输出最大得分。
    【输入输出样例】
    inverse.in inverse.out
    6
    101010
    1 1 1 1 1 1
    7
    【样例解释】
    交换 A[2]和 A[5],付出 1 + 1 = 2 的代价。
    最终序列为 111000,逆序对数为 9,得分为 9 - 2 = 7。


    这道题有两个解法,DP我们就不说了,我也不会

    然后就是贪心

    看到这道题

    我们要有两个基本的想法

    (1)教皇的两个数只可能是一个0,一个1,同时0在前,1在后

    (2)一个数只会被交换一次

    然后我们可以先求出交换之后会有贡献的数对

    然后扔到优先队列里,排序之后按顺序取,去完的就标记,知道取完为止

    下面给出代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<queue>
    using namespace std;
    inline int rd(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    char a[100006];
    int n;
    int c[100006];
    struct node{
        int x,y,z;
        bool operator < (const node c) const{
            return z<c.z;
        }
    }f[100006];
    priority_queue <node> q;
    int vis[100006];
    int l[100006];
    int main(){
        n=rd();
        scanf("%s",a+1);
        for(int i=1;i<=n;i++) c[i]=rd();
        for(int i=1;i<=n;i++){
            if(a[i]=='1') continue;
            for(int j=n;j>=i+1;j--){
                if(a[j]=='0') continue;
                node v;
                v.z=j-i-c[i]-c[j];
                v.x=i,v.y=j;
                q.push(v);
            }
        }
        int ans=0;
        while(!q.empty()){
            node h=q.top();
            q.pop();
            if(!vis[h.x]&&!vis[h.y]&&h.z>0){
                vis[h.x]=vis[h.y]=1;
                swap(a[h.x],a[h.y]);
                ans+=h.z-h.y+h.x;
            }
        }
        l[1]=0;
        for(int i=2;i<=n;i++){
            if(a[i-1]=='1') l[i]=l[i-1]+1;
            else l[i]=l[i-1];
        }
        for(int i=1;i<=n;i++) if(a[i]=='0') ans+=l[i];
        printf("%d",ans);
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    centos/7下安装mysql5.7
    ubuntu下用vagrant搭建集群环境
    ubuntu下pyspark的安装
    Ubuntu下teamviewer的安装
    volatile(一)
    synchronized(九)
    synchronized(八)
    synchronized(七)
    synchronized(六)
    synchronized(五)
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9803814.html
Copyright © 2020-2023  润新知