Educational Codeforces Round 94 (Rated for Div. 2)(A->E(分治))

A:http://codeforces.com/contest/1400/problem/A

解析:

发现每一个字符串,都包含s[n-1],所以直接打印n个s[n-1]即可

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
int answ[maxn];
int md[maxn];
int b[maxn];
int n,m;
int a[maxn];
int v[maxn];
struct node
{
    int x1,y1,x2,y2;
}st[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        string s;
        cin>>s;
        for(int i=1;i<=n;i++)
            cout<<s[n-1];
            cout<<endl;
    }
}

 

B:http://codeforces.com/contest/1400/problem/B

题意:

两个袋子大小:p,f

两种物品数量:c1,c2

两种物品所占空间:s,w

求能装的最大数量

解析:

贪心来讲,规定s<w,那么对于第一个袋子,尽量先放s,然后w,第二个袋子也是如此

根据这个贪心思路,可以对第一个袋子拿取的s数量进行枚举,s装好,再装w。c1,c2去掉之前的消耗,再对第二个袋子进行同样操作。

细节在注释里

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
struct node
{
    int x1,y1,x2,y2;
}st[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll p,f;
        ll c1,c2,s,w;
        cin>>p>>f>>c1>>c2>>s>>w;
        ll maxx=0;  //这里并没有交换s,w,第一个袋子虽然应该优先装小的,但是下面的for已经枚举到了第一种袋子的所有可能
        for(int i=0;i<=min(c1,p/s);i++)
        {
            ll s1,s2,s3;//i,s1为第一个袋子分别装s,w的数量。s2,s3分别为第二个袋子装s,w的数量
            s1=(p-s*i);
            s1=min(s1/w,c2);
            if(s<=w)  //第二个袋子优先选小
            {
                if(f>=(c1-i)*s)  //还能再装s
                {
                    s2=c1-i;
                    s3=min(c2-s1,(f-(c1-i)*s)/w);  
                }    
                else
                {
                    s2=f/s; 
                    s3=0;
                }
            }    
            else
            {
                if(f>=(c2-s1)*w)//还能再装w
                {
                    s2=c2-s1;
                    s3=min(c1-i,(f-(c2-s1)*w)/s);
                }    
                else
                {
                    s2=0;
                    s3=f/w;
                }                
            }
            maxx=max(maxx,i+s1+s2+s3);
        } 
        cout<<maxx<<endl;
    }
}

C:http://codeforces.com/contest/1400/problem/C

题意:

给出字符串s和整数x,求字符串w

s满足:

w[i+x]或w[i-x]为1,si为1,否则si为0

解析:

初始化w全为1。

遍历si的'0',把w[i]变成符合对应要求

再次遍历si的'1',如果w[i+x]==0&&w[i-x]==0,输出-1

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
struct node
{
    int x1,y1,x2,y2;
}st[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int x;
        cin>>s1>>x;
        int le=strlen(s1);
        for(int i=0;i<le;i++)
            s2[i]='1';
        for(int i=0;i<le;i++)
        {
            if(s1[i]=='0')
            {
                if(i>=x)
                    s2[i-x]='0';
                if(i+x<le)
                    s2[i+x]='0';
            }
        }
        int ok = 0;
        for(int i=0;i<le;i++)
        {
            int ok1=0,ok2=0;
            if(s1[i]=='1')
            {
                if(i>=x&&s2[i-x]=='1')
                    ok1=1;
                if(i+x<le&&s2[i+x]=='1')
                    ok2=1;
                if(!ok1&&!ok2)
                {
                    ok=1;break;
                }
            }
        }
        if(ok)
            cout<<"-1"<<endl;
        else
            {
                for(int i=0;i<le;i++)
                    cout<<s2[i];
                    cout<<endl;
            }
    }
}

D:http://codeforces.com/contest/1400/problem/D

题意:

数组ai,1<=i<j<k<l<=n,求ai=ak,aj=al的数量

解析:

枚举j,l。

假设aj==al

....aj....ax.....al,要想凑够满足题意的那四个,需要aj之前存在与ax相等的数,有几个,就能和aj,al凑成几个。所以就需要记录aj之前出现了几个ax

cnt[]记录aj之前的各个数字出现的次数。

要注意一下顺序问题,cnt[]是要在for的最后更新才行。

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=3e3+10;
const int maxn2=1e9+10;
char s1[maxn],s2[maxn];
int a[maxn];
ll cnt[maxn];
struct node
{
    int x1,y1,x2,y2;
}st[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(cnt,0,sizeof(cnt));
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        ll sum = 0 ;
        for(int j=1;j<n;j++)
        {
            int md=0;
            for(int l=j+1;l<=n;l++)
            {
                if(a[j]==a[l])
                    sum+=md;
                md+=cnt[a[l]];
            }
            cnt[a[j]]++;
        }
        cout<<sum<<endl;
    }
}

E:http://codeforces.com/contest/1400/problem/E

题意:

给出数组

操作1:[L,R]集体减1

操作2:对任意一个数,把它变成比它自己小的任意一个数

把所有数归0的最小操作数

解析:

分治

之前做过。

[L,R]都变0的话,需要r-l+1步,

与集体减1那个操作取个min就可以了

#include<bits/stdc++.h>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=5e3+10;
const int maxn2=1e9+10;
const int mod=1e9+10;
char s1[maxn],s2[maxn];
ll a[maxn];
ll cnt[maxn];
struct node
{
    int x1,y1,x2,y2;
}st[maxn];
int ac(int l,int r)
{
    if(l>r)    return 0;
    int minn=mod;
    int k;
    for(int i=l;i<=r;i++)
    {
        if(a[i]<minn)
        {
            minn=a[i];
            k=i;
        }
    }
    int md=a[k];
    for(int i=l;i<=r;i++)
        a[i]-=minn;
    return min(r-l+1,md+ac(l,k-1)+ac(k+1,r));
}
int sum=0;
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cout<<ac(1,n)<<endl;
//    cout<<sum<<endl;
}

 

posted @ 2020-08-27 18:15  liyexin  阅读(166)  评论(0编辑  收藏  举报