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;
}