1.病毒检测
滑动窗口题
例子:
2
0101010(第一位下标为1)
1)找到第一个最短的满足k条件的子串,即s[2~4],l=2,r=4
2)找出这个子串左右连续的0的个数,分别为a,b,则对于这个子串的贡献为(a+1)*(b+1)
3)之后就是滑动窗口,r到下一个1的位置,l向右移动到第一个一的位置,重复2)计算贡献
#include
using namespace std;
typedef long long ll;
const int maxn=1000050;
char s[maxn];
int main()
{
ll n,k;
scanf("%lld",&k);
scanf("%s",s+1);
n=strlen(s+1);
ll tmp=0,tp=0,fi=0,se=0,l=1,r=0,ans=0;
if(k==0){
for(int i=1;i<=n;i++){
if(s[i]=='0'){
tmp++;
if(i==n) ans+=tmp*(tmp+1)/2;
}
else{
ans+=tmp*(tmp+1)/2;
tmp=0;
}
}
printf("%lld\n",ans);
return 0;
}
for(int i=1;i<=n;i++){
if(s[i]=='1'){
tmp++;
}
if(tmp==k){
r=i;
break;
}
}
if(r==0){
printf("0\n");
return 0;
}
tp=tmp=1;
r++;
while(s[r]=='0'&&r<=n) tp++,r++;
while(s[l]=='0') tmp++,l++;
ans+=tmp*tp;
//printf("%lld %lld %lld %lld %lld\n",l,r,ans,tmp,tp);
//printf("!%lld\n",ans);
while(r<=n){
l++;r++;
tmp=tp=1;
while(s[l]=='0'){
tmp++;l++;
}
while(s[r]=='0'&&r<=n) tp++,r++;
ans+=tmp*tp;
//printf("%lld\n",ans);
}
printf("%lld\n",ans);
return 0;
}
考试成绩
每道题的答案为该题最多人选的答案
#include
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int maxn = 1050;
char s[maxn][maxn];
int num[5];
ll b[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
for(int j=1;j<=m;j++) scanf("%lld",&b[j]);
ll ans=0;
for(int i=1;i<=m;i++){
memset(num,0,sizeof(num));
for(int j=1;j<=n;j++){
num[s[j][i]-'A']++;
}
int mx=0;
for(int i=0;i<5;i++) mx=max(mx,num[i]);
ans+=b[i]*mx;
}
printf("%lld\n",ans);
}
石头碰撞
01背包。这道题的思路需要转化一下,其实这道题要求的就是把这些石头分成两部分,相差的最小值。可以感性理解下。
这样子就是最基础的01背包了,看f[i] i这个容量能不能凑出来
#include
using namespace std;
typedef long long ll;
const int maxn=10050;
int f[maxn],a[maxn];
int main()
{
int n;
scanf("%d",&n);
int sum=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
f[0]=1;
for(int i=1;i<=n;i++){
for(int j=sum;j>=a[i];j--){
f[j]|=f[j-a[i]];
}
}
int ans=sum;
for(int i=1;i<=sum;i++){
if(f[i]){
ans=min(ans,abs(i-(sum-i)));
}
}
printf("%d\n",ans);
return 0;
}
蓄水池大作战
刚看题以为很难,然后数据范围只有1000,直接暴力即可
#include
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int maxn = 1050;
vectorve[maxn];
int fa[maxn],a[maxn];
void dfs(int u,int f,int flag){
fa[u]=f;
a[u]=flag;
for(auto v:ve[u]){
if(v==f) continue;
dfs(v,u,flag);
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i