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 <bits/stdc++.h>
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<bits/stdc++.h>
#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 <bits/stdc++.h>
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<bits/stdc++.h>
#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;
vector<int>ve[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<n;i++){
int x,y;
scanf("%d%d",&x,&y);
ve[x].push_back(y);
ve[y].push_back(x);
}
dfs(1,1,0);
int q;
scanf("%d",&q);
while(q--){
int op,x;
scanf("%d%d",&op,&x);
if(op==1){
dfs(x,fa[x],1);
}
else if(op==2){
while(fa[x]!=x){
a[x]=0;
x=fa[x];
}
a[1]=0;
}
else{
if(a[x]) printf("1\n");
else printf("0\n");
}
}
}