A
题意:a列表,b列表,只能修改字母,问最少修改几次字母让a,b相同。
思路:mp搞一下,没读题看样例错了半天,
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
string s[15] = { "M", "L" ,"S" ,"XL" , "XS" ,"XXL" , "XXS" ,"XXXL" ,"XXXS" };
int main(){
int n ;
map<string,int>mp;
map<string,int>mp1;
cin >> n ;
string x ;
int res = 0 ;
for( int i = 0 ; i < n ; i++ ){
cin >> x;
mp[x] ++ ;
}
for( int i = 0 ; i < n ; i++ ){
cin >> x;
if( !mp[x] ) res ++ ;
else mp1[x]++;
}
for( int i = 0 ; i < 9 ; i++ ){
if( mp1[s[i]] && mp[s[i]] < mp1[s[i]] ){
res += ( mp1[s[i]] - mp[s[i]] );
}
}
cout << res << endl;
return 0 ;
}
B
题意:一个递增数列 0 ,a1,a2…an , M
一个灯会在每一段 开 关 开 关 开 关 …开 关 这样交替,初始开灯时间就是 :
a1 - 0 + a3 - a2 +…+ …
最多在其中添加一个数字仍要递增并且使其开的时间最长。
思路:预处理下不添加数字的开灯的前缀和,以及添加一个可能的数字后开灯间隔改变后的前缀和即可。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e5 + 66 ;
LL a[AX] ;
LL sum1[AX] ;
LL sum2[AX] ;
int main(){
int n , m ;
cin >> n >> m ;
for( int i = 1 ; i <= n ; i++ ){
cin >> a[i] ;
}
a[0] = 0 ;
a[n+1] = m ;
for( int i = 1 ; i <= n + 1 ; i++ ){
if( i % 2 ){ sum1[i] = sum1[i-1] + a[i] - a[i-1] ; sum2[i] = sum2[i-1] ;}
else { sum2[i] = sum2[i-1] + a[i] - a[i-1]; sum1[i] = sum1[i-1] ; }
}
LL res = sum1[n+1] ;
for( int i = 1 ; i <= n ; i++ ){
LL tmp = sum1[i-1] + sum2[n+1] - sum2[i] + ( a[i] - a[i-1] - 1 ) ;
res = max( res , tmp ) ;
}
cout << res << endl;
return 0 ;
}
C
题意:给n个线段,问被覆盖1-n次的点的个数。
思路:如果数据范围小的话,可以直接排序,维护前缀和,但是1e18是不可能的,
又因为n只有2e5 , 那么点最多4e5个,排序后,遍历各点,是右端点就–,左端点就++,每次的贡献就是两个端点之间的长度。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 2e5 + 66 ;
LL res[AX];
map<LL,LL>mp;
int main(){
int n ;
cin >> n ;
LL l , r ;
for( int i = 0 ; i < n ; i++ ){
cin >> l >> r ;
mp[l]++ ;
mp[r+1]-- ;
}
LL x = 0 , last = 0 ;
for( auto it : mp ){
res[x] += it.first - last ;
last = it.first;
x += it.second ;
}
for( int i = 1 ; i <= n ; i++ ){
cout << res[i] << ' ';
}cout << endl;
return 0 ;
}