Codeforces Round #256 (Div. 2) A/B/C/D

A. Rewards

水题

#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

int main()
{
    int a1,a2,a3,b1,b2,b3,s,t1,t2,sum1,sum2;
    while(scanf("%d%d%d",&a1,&a2,&a3)!=EOF)
    {
        scanf("%d%d%d",&b1,&b2,&b3);
        scanf("%d",&s);
        sum1 = a1+a2+a3;
        sum2 = b1+b2+b3;
        if(sum1>=5)
        {
            t1 = sum1/5;
            if(sum1%5) t1++;
        }
        else if(sum1>0) t1 = 1;
        else t1 = 0;
        if(sum2>=10)
        {
            t2 = sum2/10;
            if(sum2%10) t2++;
        }
        else if(sum2>0) t2 = 1;
        else t2 = 0;
        if(t1+t2>s) puts("NO");
        else puts("YES");
    }
    return 0;
}

B. Suffix Structures

题意:给你两个字符串,要把a串变为b串,如果只需要删除某些字符就能达到目的就输出automaton

如果只通过交换某些字符就输出array,如果两种操作都需要才能达到目的就输出both,如果两种操作

同时使用都不行则输出need
tree.

算法:

这个其实情况很复杂的,必须保持头脑清晰清晰清晰~

1、首先如果两个串是相同的则输出array。

2、如果a串长度小于b串长度或者b串中的对应字母在a串中个数不够或者种类不够都是need
tree.

3、如果a串长度等于b串长度,且a串中能找到对应的b串中的字母则输出array.

4、如果a串长度大于b串长度,b串中的字母在a串中依次出现则输出automaton.如果虽然都出现了但是

顺序不一样,则输出both。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>

using namespace std;

char s1[110],s2[110];
vector<int> c;
int cnt1[30],cnt2[30];

int main()
{
    int flag1,flag2,d,flag;
    while(scanf("%s%s",s1,s2)!=EOF)
    {
        if(strcmp(s1,s2)==0)
        {
            printf("array\n");
            continue;
        }
        flag1 = flag2 = flag = 0;
        c.clear();
        memset(cnt1,0,sizeof(cnt1));
        memset(cnt2,0,sizeof(cnt2));
        int len1 = strlen(s1);
        int len2 = strlen(s2);
        if(len1>len2) flag1 = 1;
        for(int i=0;i<len2;i++)
            cnt2[s2[i]-'a']++;
        for(int j=0;j<len1;j++)
            cnt1[s1[j]-'a']++;
        for(int i=0;i<len2;i++)
        {
            if(cnt2[s2[i]-'a'] > cnt1[s2[i]-'a'])
            {
                flag = 1;
                break;
            }
        }
        if(flag || len1<len2)
        {
            printf("need tree\n");
            continue;
        }
        for(int i=0;i<len1;i++)
        {
            if(s1[i]==s2[0])
                c.push_back(i);
        }
        for(int i=0;i<c.size();i++)
        {
            int t = 1;
            for(int j=c[i]+1;j<len1;j++)
            {
                if(s1[j]==s2[t])
                    t++;
            }
            if(t == len2)
            {
                flag2 = 1;
                break;
            }
        }
        if(flag1 && flag2)
            printf("automaton\n");
        else if(flag1 && !flag2)
            printf("both\n");
        else if(!flag1 && !flag2)
            printf("array\n");
    }
    return 0;
}

C. Painting Fence

题意:有n个长度为ai的木条。然后有一个油漆刷,木条宽度和油漆刷的宽度都为1,要把

木条都涂色。且油漆刷刷到的地方都要有木块。问最少需要刷多少次。

算法:记忆化搜索

1、横向刷的下面一定是横向刷。

2、刷完了下面共同的长度后会把木条分成断开的几截,每一截由若干木条的上半部分未刷油漆的组成。

每一部分要么就是竖着刷要么就是横着刷,这时比较两种刷法的次数,取小者。[l,r]的部分竖着刷要刷

r-l+1下,横着刷还是先刷公共部分,再看上面分成几截,于是又出现了相同的子问题。用dfs递归解决。

#include<cstdio>
#include<iostream>
#include<cstring>
#define maxn 5010

using namespace std;

typedef long long ll;
ll a[maxn];

ll min(ll x,ll y)
{
    return x<y?x:y;
}

ll work(int l,int r,int cen)
{
    ll mi = a[l];
    for(int i=l+1;i<=r;i++)
        mi = min(mi,a[i]);
    ll sum = mi-cen,s = r-l+1;
    int last = l;
    for(int i=l;i<=r;i++)
    {
        if(a[i]==mi)
        {
            if(last<i) sum+=work(last,i-1,mi);
            last = i+1;
        }
    }
    if(last<=r) sum+=work(last,r,mi);
    return min(sum,s);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        ll ans = work(1,n,0);
        printf("%I64d\n",ans);
    }
    return 0;
}

D. Multiplication Table

题意:n行m列的乘法表,为第k大的数是哪个。

比如:2*3的乘法表为     1    2    3

2    4    6

算法:二分查找。

由于最大的数为n*m=25*10^10,想到二分。第k大的数就是说有k个小于等于他的数(这种说法也不准确),

反正就是第一个找到的这样的最小的数。

充分利用乘法表的特点,每一行都是行数乘以1-m。所以找比小于等于x的数就是min(m,x/i)。

P.S 。。。反正我是没想到这个解法啦。。。o(╯□╰)o。。。学习了。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>

using namespace std;
typedef long long ll;

ll k,n,m;

ll min(ll x,ll y)
{
    return x<y?x:y;
}

ll check(ll x)
{
    ll sum = 0;
    for(int i=1;i<=n;i++)
        sum += min(m,x/i);
    return sum;
}
int main()
{
    ll ans;
    while(scanf("%I64d%I64d%I64d",&n,&m,&k)!=EOF)
    {
        ll l = 1,r = n*m;
        while(l<=r)
        {
            ll mid = (l+r)>>1;
            if(check(mid)>=k)
            {
                ans = mid;
                r = mid-1;
            }
            else l = mid+1;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

Codeforces Round #256 (Div. 2) A/B/C/D,布布扣,bubuko.com

时间: 2024-10-06 14:37:06

Codeforces Round #256 (Div. 2) A/B/C/D的相关文章

Codeforces Round #256 (Div. 2)——Painting Fence

题目连接 题意: n个木条,输入n个木条的高度,每个木条的宽度均为1.现在有长宽均为1的刷子,每次可以选择横着刷或者竖着刷,每次刷的时候不能离开木条,问将所有木条均涂色至少需要刷几次.(刷的时候可以经过已经被刷过的地方) n (1?≤?n?≤?5000),1?≤?ai(高度)?≤?109 分析: 分析一下横着和竖着的关系:假设现在已经有一个操作集合S是答案,那么集合中的操作顺序是可以改变的,即横和竖的顺序可以改变(因为可以经过已经涂色的木条),那么不妨先横着涂色.对于当前[l,r]的区间,答案不

Codeforces Round #256 (Div. 2/B)/Codeforces448B_Suffix Structures(字符串处理)

解题报告 四种情况相应以下四组数据. 给两字符串,推断第一个字符串是怎么变到第二个字符串. automaton 去掉随意字符后成功转换 array 改变随意两字符后成功转换 再者是两个都有和两个都没有 #include <iostream> #include <cstdio> #include <cstring> #include <stdlib.h> #include <algorithm> #include <cmath> usi

Codeforces Round #256 (Div. 2/C)/Codeforces448C_Painting Fence(分治)

解题报告 给篱笆上色,要求步骤最少,篱笆怎么上色应该懂吧,,,刷子可以在横着和竖着刷,不能跳着刷,,, 如果是竖着刷,应当是篱笆的条数,横着刷的话,就是刷完最短木板的长度,再接着考虑没有刷的木板,,, 递归调用,,, #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define inf 999999999999999 using namespace

Codeforces Round #256 (Div. 2) Multiplication Table

刚刚开始想到一种很暴力但还行的方法,不过在和TK讨论的过程中引出了一个更好的算法 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; long long n,m,k; long long check(long long x) { long long ans=0; for(int i=1;i<=n;i++) { ans

Codeforces Round #256 (Div. 2)

泛泛解: D:求K大,如果我们二分枚举,如果有O(N)的方法统计,就OK了,先枚举,我们对每一行的统计能够达到O(1),所以很简单了. E:有思路,但是代码能了太弱了,DFS学得太水. 我们发现其实就是一个深度递归结构,只有100000个元素,所以这是一个突破点. 先求出所有因子,然后枚举因子,出现的话深度遍历,结束条件是达到第K层或者因子是1,注意:K大于100000时,要变为100000,因为不可能层数大于100000: C:分治+贪心. 这道真是好题,题解的思路是:对区间(L,R)的点贪心

Codeforces Round #256 (Div. 2)D 二分答案

D. Multiplication Table time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Bizon the Champion isn't just charming, he also is very smart. While some of us were learning the multiplication tabl

Codeforces Round #256 (Div. 2) B (448B) Suffix Structures

题意就是将第一个字符串转化为第二个字符串,支持两个操作,一个是删除,一个是更换字符位置. 简单的字符串操作!! AC代码如下: #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define M 50010 #define inf 100000000 using namespace std; char a[1005],b[1005]; int la,lb; b

递归解Codeforces Round #256 (Div. 2)C. Painting Fence

#include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector> #include<algorithm> using namespace std; in

Codeforces Round #256 (Div. 2) C (448C)Painting Fence

分治!首先是一大块,贪行刷和竖刷的最小,再转化为小块............ AC代码如下: #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n; int a[5005]; int solve(int l,int r) { int i,j; int len=r-l+1; int height=a[l]; for(i=l;i<=r;i++) if(a[i]&