CF #251 div2

2014-06-05 22:23:48

A,B两题直接水过(坑爹的是程序不鲁棒,被hack两次!)

C:

题意&思路:拆分一串数成k份,要求其中p份各自和为偶数,k-p份各自和为奇数。分析:奇数能转化成偶数(2奇凑1偶),而偶数不能凑成奇数,所以先考虑奇数总数是否大于k-p,再考虑到:如果奇数总数减去看k-p(需求数)为奇数的话,也是不行的(转化到偶数需要偶数个奇数);最后考虑到偶数总数加上多余的奇数/2仍小于p(需求数),也不行。所以把以上三种情况考虑了之后,剩下的情况一定是可行的,这点很有用。接下来就是关键的步骤:输出k-p-1个奇数(如果k-p-1<=0,不输出),留下一个奇数!再输出p-1个偶数(如果p-1<=0,不输出),留下一个偶数。为什么要各留下一个奇数一个偶数呢?好吧,先来考虑三种情况(1)p==0,k-p!=0,不需要偶数,只要奇数,这时如果之前把需要的奇数都输出了,那就会剩下一堆偶数没有处理,所以这时留下的奇数和偶数一起输出。(2)p!=0,k-p==0,不需要奇数,只要偶数,同理如果把偶数都输出了,会剩下一堆奇数没有处理,所以这时留下的奇数和偶数一起输出。(3)p!=0,k-p!=0,这时留下的一奇一偶显得有点多余,于是先把奇数输出,再把剩下的奇数偶数输出。(或者把偶数输出,剩下的奇数偶数输出)。

#include <cstdio>
#include <iostream>
using namespace std;
int odd[100005],even[100005];
int main(){
    int n,k,p,u,ocnt = 0,ecnt = 0,v;
    scanf("%d %d %d",&n,&k,&p);
    u = k - p;
    for(int i = 0; i < n; ++i){
        scanf("%d",&v);
        if(v & 1)
            odd[ocnt++] = v;
        else
            even[ecnt++] = v;
    }
    if(ocnt < u || (ocnt - u) & 1 || ecnt + ((ocnt - u)>>1) < p){
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    for(int i = 0; i < u - 1; ++i)
        printf("1 %d\n",odd[--ocnt]);
    for(int i = 0; i < p - 1; ++i){
        if(ecnt)
            printf("1 %d\n",even[--ecnt]);
        else{
            printf("2 %d %d\n",odd[ocnt - 1],odd[ocnt - 2]);
            ocnt -= 2;
        }
    }
    if(u && p)
        printf("1 %d\n",odd[--ocnt]);
    printf("%d",ocnt + ecnt);
    while(ocnt)
        printf(" %d",odd[--ocnt]);
    while(ecnt)
        printf(" %d",even[--ecnt]);
    puts("");
    return 0;
}

D:

题意&思路:贪心策略,已无力赘述。。。。有两个版本

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100000;
long long n,m;
long long a[maxn + 5],b[maxn + 5],ae[maxn + 5],be[maxn + 5],amin = 1000000001,bmax = 0;

bool cmpmax(int a,int b){
    return a > b;
}
bool cmpmin(int a,int b){
    return a < b;
}
int main(){
    scanf("%I64d %I64d",&n,&m);
    for(int i = 1; i <= n; ++i){
        scanf("%I64d",&a[i]);
        amin = min(amin,a[i]);
    }
    for(int i = 1; i <= m; ++i){
        scanf("%I64d",&b[i]);
        bmax = max(bmax,b[i]);
    }
    sort(a + 1,a + n + 1,cmpmin);
    sort(b + 1,b + m + 1,cmpmax);
    ae[n] = n;
    be[m] = m;
    for(int i = n - 1; i >= 1; --i){
        if(a[i] == a[i + 1])
            ae[i] = ae[i + 1];
        else
            ae[i] = i;
    }
    for(int i = m - 1; i >= 1; --i){
        if(b[i] == b[i + 1])
            be[i] = be[i + 1];
        else
            be[i] = i;
    }
    long long ap = 1,bp = 1;//positions
    long long t1,t2,l1 = ae[1],l2 = be[1],sum = 0;
    while(amin < bmax){
        if(l1 <= l2){
            if(l1 < n){
                amin = min(a[ae[ap] + 1],bmax);
                sum += l1 * (amin - a[ap]);
                ap = ae[ap] + 1;
                l1 = ae[ap];
            }
            else{ //l1 == n
                sum += n * (bmax - amin);
                amin = bmax;
            }
        }
        else{
            if(l2 < m){
                bmax = max(b[be[bp] + 1],amin);
                sum += l2 * (b[bp] - bmax);
                bp = be[bp] + 1;
                l2 = be[bp];
            }
            else{
                sum += m * (bmax - amin);
                bmax = amin;
            }
        }
    }
    cout << sum <<endl;
    return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
long long a[100005],b[100005],sum;
bool cmp1(long long a,long long b){ return a < b;}
bool cmp2(long long a,long long b){ return a > b;}
int main(){
    int n,m; cin>>n>>m;
    for(int i=0;i<n;++i) cin>>a[i]; for(int i=0;i<m;++i) cin>>b[i];
    sort(a,a+n,cmp1); sort(b,b+m,cmp2);
    for(int i=0;i<min(n,m);++i) if(b[i]>a[i]) sum += b[i]-a[i];
    cout<<sum<<endl; return 0;
}

 

posted @ 2014-06-05 22:38  Naturain  阅读(138)  评论(0编辑  收藏  举报