码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 557

时间:2015-07-28 16:05:18      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:



/*A没啥说的,,先都满足最小然后优先满足前面的*/

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

int main()
{
    int m;
    scanf("%d",&m);
    int a[5][2];
    int b[5];
    int i;
    int minn=0;
    for(i=0;i<3;i++)
    {
        scanf("%d %d",&a[i][0],&a[i][1]);
        minn+=a[i][0];
        b[i]=a[i][0];
    }
    m=m-minn;
    for(i=0;i<=2;i++)
    {
        if(m<=0) break;
        if(m>=(a[i][1]-a[i][0]))
        {
            b[i]=a[i][1];
            m-=(a[i][1]-a[i][0]);
        }
        else
        {
            b[i]+=m;
            m=0;
        }
    }
    printf("%d %d %d\n",b[0],b[1],b[2]);

    return 0;
}

/*B这么水错了N次,,,,,注意男生女生的水同性是一样多的。。。。。还有LONG LONG*/

#include <iostream>
#include<bits/stdc++.h>

using namespace std;
long long int a[500001];
int main()
{
    long long int n,w;
    scanf("%lld%lld",&n,&w);
    long long int i;
    for(i=0;i<2*n;i++) scanf("%d",&a[i]);
    sort(a,a+2*n);
    double sum=0;
    if(a[n]>=2*(double)a[0])
    {
        sum=3*n*a[0];
    }
    else sum=3*n*(double)a[n]/2;
    if(sum>=w) sum=w;
    printf("%llf\n",sum);
    return 0;
}
C:很多桌腿,,,,砍掉一部分,,,使剩下的最长的桌腿数一半以上,,,,求最小代价。。。。。。。

超时代码。。。。。

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

struct node
{
    int l,d;
}a[100001];

bool cmp(node a1,node a2)
{
    return a1.d<a2.d;
}
int w[100001];

int main()
{
    int m;
    //int nnnnn=0;
    scanf("%d",&m);
    int i;
    for(i=0;i<m;i++) {scanf("%d",&a[i].l);w[a[i].l]++;}
    for(i=0;i<m;i++)
    {
        scanf("%d",&a[i].d);
        //nnnnn+=a[i].d;
    }
    sort(a,a+m,cmp);
    //for(i=0;i<m;i++){ printf("%d**%d\n",a[i].l,a[i].d);}
    long long int sum;
    int k,j;
    long long int ans=10000000;
    for(i=0;i<m;i++)
    {
        sum=0;
        k=m-2*w[a[i].l]+1;
        //printf("k=%d\n",k);
        for(j=0;j<m;j++) if(a[i].l<a[j].l) {sum+=a[j].d; k--;}
        for(j=0;j<m;j++)
        {
            if(a[i].l==a[j].l) continue;
            else if(a[i].l>a[j].l&&k>0)
            {
                sum+=a[j].d;
                k--;
            }
            else if(k==0) break;
        }
        ans=min(ans,sum);

        //printf("%d**\n",sum);
    }
    //printf("%d\n",nnnnn);
    printf("%lld\n",ans);
    return 0;
}
很朴素但是思路也是从这里来的,,,,就是每次确定一组留下的最长,,,,,大于的都删掉,,,小于的删代价小的。。。。。。

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 100001;

struct node
{
    int l, d;
} s[maxn];

int num[maxn], sum[maxn], dnum[205];

bool cmp(node a, node b)
{
    return a.l < b.l;
}
int main()
{
    int n, low, up;
    scanf("%d", &n);
    low = maxn, up = 0;      //优化循环,,,看看给的长度的范围
    int i;
    for(i = 0; i < n; i++)
    {
        scanf("%d", &s[i].l);
        low = min(low, s[i].l);
        up = max(up, s[i].l);
    }
    for(i = 0; i < n; i++)scanf("%d", &s[i].d);
    for(i = 0; i < n; i++)
    {
        num[s[i].l]++;      //记录有多少个
        sum[s[i].l] += s[i].d;         //记录这一类的和
    }
    for(i = up; i >= low; i--) sum[i] += sum[i+1];  //记录和,,,到时候好减
    sort(s, s+n, cmp);
    int cnt = 0;
    int k = 0, temp;
    int ans = inf;
    for(int i = low; i <= up; i++)
    {
        if(num[i] == 0)
            continue;
        while(cnt<n && s[cnt].l<i)  //i表示的是长度
            dnum[s[cnt++].d]++;
        int p = k;
        k += num[i];
        temp = sum[i+1];
        if(p >= num[i])
            for(int j = 1; j < 201; j++) //用代价来枚举——关键!
                if(dnum[j])
                {
                    if(p < num[i])
                        break;
                    if(p-num[i]+1 < dnum[j])
                    {
                        temp += (p-num[i]+1)*j;
                        break;
                    }
                    temp += dnum[j]*j;
                    p -= dnum[j];
                }
        ans = min(ans, temp);
    }
    printf("%d\n", ans);
    return 0;
}
/*D图论。。*/

问最少加几条线能形成奇个节点的环,,,,,而又有几种方法?

其实也没有啥图论的,,,,,,分情况讨论遍历被~

我不知道这算什么。。。。

就是遍历的时候将点一黑一白的染色,,,最后连线的话连相同颜色的就好

题不难就是要慢慢想。。。。。

#include <iostream>
#include<bits/stdc++.h>

using namespace std;

long long int odd,even;
vector <int> G[100001];
int loop=0;
int bin=0;
int ps[100001];
int vis[100001]={0};

void dfs(int n,int cur)
{
    if(G[n].size()>=2) bin=1; //只要有一组大于二,那个情况就是不成立的
    if(cur&1) {odd++; ps[n]=1; }
    else {even++; ps[n]=0; }
    for(int i=0;i<G[n].size();i++)
    {
        int nw=G[n][i];
        if(!vis[nw])
        {
            vis[nw]=1;
            dfs(nw,cur+1);
        }
        if(ps[nw]==ps[n]) loop=1;      //成环
    }
}

int main()
{
    long long int n,m;
    scanf("%lld %lld",&n,&m);
    if(m==0) //没有边必然加三条边。。
    {
        printf("3 %lld\n",n*(n-1)*(n-2)/6);
        return 0;
    }
    int i;
    for(i=0;i<m;i++)
    {
        int s,t;
        scanf("%d %d",&s,&t);
        G[s].push_back(t);            //想了好久还是得用这个。。。。太方便了
        G[t].push_back(s);            //就是存储每个点连着几个点
    }
    long long int ans = 0;
    for(i=1;i<=n;i++)        //////所有的点都遍历到做好标记
    {
        if(!vis[i])
        {
            vis[i]=1;
            odd=even=0;
            dfs(i,0);
            ans+=odd*(odd-1)/2+even*(even-1)/2;   //选两个相同的点连线(最后一种情况)
        }
    }
    if(loop) //本来有环不用加
    {
        printf("0 1\n"); return 0;
    }
    if(!bin) //不存在3点或以上相连的地方,,,需要加两条边(任选一条边以及除了端点之外的任一点)
    {
        printf("2 %lld\n",m*(n-2));
        return 0;
    }
    printf("1 %lld\n",ans);         //加一条
    return 0;
}

E:奇回文字串:1.3.5.。。。。位置的字符构成回文字串

DP,字典树。

妈蛋写在下一篇吧。。。。。。。


版权声明:本文为博主原创文章,未经博主允许不得转载。

codeforces 557

标签:

原文地址:http://blog.csdn.net/zhangwenchi/article/details/47099893

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!