Educational Codeforces Round 46 (Rated for Div. 2)

A.
非常暴力枚举一下即可

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
int main()
{
    map<string,int>mp1,mp2;
    int n,i,j,k;
    cin>>n;
    string str;
    for(i=1;i<=n;i++){
        cin>>str;mp1[str]++;
    }
    for(i=1;i<=n;i++){
        cin>>str;mp2[str]++;
    }
    int ans=0;
    ans+=mp2["M"]+mp2["S"]+mp2["L"]-(min(mp1["M"],mp2["M"])+min(mp1["S"],mp2["S"])+min(mp1["L"],mp2["L"]));
    ans+=mp2["XS"]+mp2["XL"]-(min(mp1["XS"],mp2["XS"])+min(mp1["XL"],mp2["XL"]));
    ans+=mp2["XXS"]+mp2["XXL"]-(min(mp1["XXS"],mp2["XXS"])+min(mp1["XXL"],mp2["XXL"]));
    ans+=mp2["XXXS"]+mp2["XXXL"]-(min(mp1["XXXS"],mp2["XXXS"])+min(mp1["XXXL"],mp2["XXXL"]));
    cout<<ans<<endl;

    return 0;
}

B.
枚举在每个区间处加入新的标志改变亮灭即可,但是如何巧妙简洁地写出表达式还是挺需要想象力的…

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int a[N],b[N];
int main()
{
    int n,m,i,j,k;
    cin>>n>>m;
    for(i=1;i<=n;i++)scanf("%d",&a[i]);
    int sit=1;
    for(i=1;i<=n;i++){
        b[i]=b[i-1]+sit*(a[i]-a[i-1]);//sit用于判断这个区间是亮还是灭
        sit^=1;
    }
    b[n+1]=b[n]+sit*(m-a[n]);//不要漏了最后一个区间
    int ans=b[n+1];
    for(i=1;i<=n;i++)ans=max(ans,b[i]*2-b[n+1]+m-a[i]-1);//m-a[i]-(b[n+1]-b[i])-1求出在
    // 当前区间改变状态后此区间后面的亮灯时长,加上前面不变的就是总的亮灯时长
    cout<<ans<<endl;

    return 0;
}

C.
朴素的想法是建立一个cnt数组,统计每一个点被多少个区间覆盖了,然后我们发现其实并不用真的把所有点都模拟出来,只要在区间的l处+1,区间的r+1处-1即可,最后利用前缀和从前加到后就可以求出该区间的seg的覆盖数。区间的端点过大,因此要用map离散化一下。然后注意到端点之间的整个区间内的seg覆盖数肯定都是相同的即可。

#include<cstdio>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
//#define ll long long
map<ll,ll>M;
ll A[200005],x,y,n,l;
int main()
{
    scanf("%lld", &n);
    for (l = n; l >= 1; --l) {
        scanf("%lld%lld", &x, &y);
        ++M[x];//在l处+1
        --M[y + 1];//在r+1处-1
    }
    x = 0;//注意x从0开始
    for (auto it:M) {
        A[x] += it.first - l;//从前一个到这一个点中间所有点的区间覆盖数都是相同的
        l = it.first;//更新
        x += it.second;//注意it.second有正有负,依赖的是前缀和来求出当前区间的情况
    }
    for (l = 1; l <= n; ++l)
        printf("%lld ", A[l]);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值