一、牛牛冲钻五(模拟)


cpp
#include<iostream>
using namespace std;
int main(){
int t,n,k;
string s;
cin>>t;
while(t--){
cin>>n>>k>>s;
int ret=0;//统计加了多少星
for(int i=0;i<n;++i)
if(s[i]=='L') --ret;
else if(i-1>=0&&i-2>=0&&s[i-1]=='W'&&s[i-2]=='W') ret+=k;
else ++ret;
cout<<ret<<endl;
}
}
二、最长无重复子数组(变长滑动窗口)
cpp
class Solution {
public:
int hash[100001];//标记重复数
int maxLength(vector<int>& arr) {
int n=arr.size();
int ret=0;
for(int left=0,right=0;right<n;++right){
++hash[arr[right]];
while(hash[arr[right]]>1) --hash[arr[left++]];
ret=max(ret,right-left+1);//求最大 不需要在while里面更新 求最小才需要
}
return ret;
}
};
三、重排字符串(贪心)


cpp
//该题就是贪心 要先统计数量最多的那个
#include<iostream>
#include<string>
using namespace std;
int main(){
int n;
string s;
cin>>n>>s;
int hash[26]={0};//统计字符
char maxchar;//记录最大字符
int maxcount=0;//以及他的最大数量
for(auto&ch:s)
if(++hash[ch-'a']>maxcount){//找到更大的就更新一下
maxcount=hash[ch-'a'];
maxchar=ch;
}
//这个时候我们先看看是否超过了
if(maxcount>(n+1)/2) cout<<"no"<<endl;
else{
cout<<"yes"<<endl;
//开始按顺序填那个最多的
int index=0;
while(maxcount--){
s[index]=maxchar;
index+=2;
}
//继续填剩下的
for(int i=0;i<26;++i)
if(hash[i]&&i!=maxchar-'a')
while(hash[i]--){
if(index>=n) index=1;
s[index]=i+'a';
index+=2;
}
cout<<s<<endl;
}
}
四、乒乓球筐(哈希)


cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string a,b;
while(cin>>a>>b){
int hash[26]={0};
for(auto&ch:a) ++hash[ch-'A'];
bool ret=true;
for(auto&ch:b)
if(--hash[ch-'A']<0){
ret=false;
break;
}
cout<<(ret?"Yes":"No")<<endl;//多组 不能return 那就用一个bool值
}
}
// 64 位输出请用 printf("%lld")
五、组队竞赛(排序+贪心)


cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+5;
int n;
long long a[N*3];
int main() {
cin>>n;
for(int i=0;i<n*3;++i) cin>>a[i];
sort(a,a+3*n);//排序之后 我们就取倒数第二个人的成绩
int pos=3*n-2,count=0;
long long ret=0;
while(++count<=n){
ret+=a[pos];
pos-=2;
}
cout<<ret<<endl;
}
// 64 位输出请用 printf("%lld")
六、删除相邻数字的最大分数(预处理+状态dp)


cpp
#include <iostream>
using namespace std;
//状态dp 也就是不可同时取
const int N=1e4+1;
int sum[N],f[N],g[N];//第一个是总和数组 第二个是i位置选了的dp数组 第二个是i位置不选的dp数组
int n;
int main() {
cin>>n;
int x;
while(n--){
cin>>x;
sum[x]+=x;
}
//然后进行dp
for(int i=1;i<N;++i){
f[i]=g[i-1]+sum[i];//当前位置选了
g[i]=max(f[i-1],g[i-1]);//当前位置没选
}
cout<<max(f[N-1],g[N-1])<<endl;
}
// 64 位输出请用 printf("%lld")
七、平方数(数学)


cpp
#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;
int main(){
LL x;
cin>>x;
LL a=sqrt(x);
LL x1=a*a,x2=(a+1)*(a+1);
if(x2-x>x-x1) cout<<x1<<endl;
else cout<<x2<<endl;
}
八、**分组(枚举+二分)


cpp
#include<iostream>
#include<unordered_map>
using namespace std;
int n,m;
unordered_map<int,int> cnt;//统计各个声部各有多少人数
bool check(int x){//查看每组最多x人的时候最少能分几组
int g=0;
for(auto&[a,b]:cnt)
g+=b/x+(b%x!=0);
return g<=m;
}
int main(){
cin>>n>>m;
int x;
int hmax=0;//统计最多人数的声部
for(int i=0;i<n;++i){
cin>>x;
hmax=max(hmax,++cnt[x]);
}
int kinds=cnt.size();//有多少种类
if(kinds>m) cout<<-1<<endl;//种类太多的话就无法安排
else{
// for(int i=1;i<=hmax;++i) 暴力枚举
// if(check(i)){
// cout<<i<<endl;
// break;
// }
//二分
int left=1,right=hmax;
while(left<right){//左区间端点法
int mid=left+(right-left)/2;
if(check(mid)) right=mid;
else left=mid+1;
}
cout<<left<<endl;
}
}
九、【模板】拓扑排序


cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int N=2e5+1;
int in[N];//统计入度信息
vector<vector<int>> edges(N);//每个点对应边的集合
queue<int> q;//进行bfs
vector<int> ret;//获取最终结果
int n,m,a,b;
int main() {
cin>>n>>m;
while(m--){//开始建图
cin>>a>>b;
edges[a].emplace_back(b);
++in[b];//统计入度信息
}
//此时图建完了 然后开始把所有入度为0的点都丢进去
for(int i=1;i<=n;++i)
if(in[i]==0) q.push(i);
//开始进行bfs
while(!q.empty()){
int a=q.front();
ret.emplace_back(a);
q.pop();
//把跟t有关的入度删了
for(auto&b:edges[a])
if(--in[b]==0) q.push(b);
}
//检查一下是否符合要求
if(ret.size()!=n) cout<<-1;//说明不是有向无环图
else{
for(int i=0;i<n-1;++i)
cout<<ret[i]<<" ";
cout<<ret[n-1];
}
}
// 64 位输出请用 printf("%lld")
十、字符串替换(模拟)


cpp
class StringFormat {
public:
string formatString(string A, int n, vector<char> arg, int m) {
string ret;
int j=0;//用来标记参数列表
for(int i=0;i<n;++i)
if(A[i]=='%'){
ret+=arg[j++];
++i;
}
else ret+=A[i];
while(j<m) ret+=arg[j++];
return ret;
}
};
十一、**神奇数(数学)
cpp
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
bool isprimenum(int x){//判断该数是否是质数 用试除法
if(x<2||x%2==0) return false;//偶数肯定不是质数
int n=sqrt(x);
for(int i=3;i<=n;i+=2)//奇数除以偶数肯定不能整除
if(x%i==0) return false;
return true;
}
bool check(int x){//判断是否是神奇数
vector<int> nums;
while(x){
nums.emplace_back(x%10);
x/=10;
}
int n=nums.size();
for(int i=0;i<n;++i)//枚举十位数
for(int j=0;j<n;++j)//枚举个位数
if(i!=j&&nums[i]!=0&&isprimenum(nums[i]*10+nums[j]))
return true;
return false;
}
int a, b;
int main() {
cin>>a>>b;
int ret=0;
for(int i=max(10,a);i<=b;++i)
if(check(i)) ++ret;
cout<<ret<<endl;
}
// 64 位输出请用 printf("%lld")
十二、DNA序列(定长滑动窗口)


cpp
#include <iostream>
#include <string>
using namespace std;
string s;
int N;//限定子串的长度
int main() {
cin>>s>>N;
int maxCount=0;//用来统计最大的count
int Count=0;//用来统计窗口里的c+g
int begin=-1;//用来统计初始位置
int n=s.size();
int left=0,right=0;//滑动窗口
for(;right<N-1;++right) //先把前n-1个进去
Count+=(s[right]=='C'||s[right]=='G');
for(;right<n;++right,++left){
Count+=(s[right]=='C'||s[right]=='G');
if(Count>maxCount){
maxCount=Count;
begin=left;
}
Count-=(s[left]=='C'||s[left]=='G');
}
cout<<s.substr(begin,N)<<endl;
}
// 64 位输出请用 printf("%lld")
十三、*小乐乐改数字(模拟)


cpp
#include <iostream>
#include <string>
using namespace std;
//'A' 的 ASCII 码是 65
//'a' 的 ASCII 码是 97
//'0' 的 ASCII 码是 48
//' ' (空格) 的 ASCII 码是 32
string s;
int main() {
cin>>s;
for(auto&ch:s)
if(ch&1) ch='1';
else ch='0';
cout<<stoi(s)<<endl;//自动处理前导零
}
// 64 位输出请用 printf("%lld")
十四、*十字爆破(预处理+模拟)


cpp
//可以提前把每行每列的值都给他存起来
#include<iostream>
using namespace std;
const int N=1e6+1;
typedef long long LL;
LL row[N],col[N];//统计每行每列的值
int n,m;
int main(){
scanf("%d %d",&n,&m);
LL nums[n][m];//这个用NN建的话空间太大了
for(int i=0;i<n;++i)
for(int j=0;j<m;++j){
scanf("%lld",&nums[i][j]);
row[i]+=nums[i][j];
col[j]+=nums[i][j];
}
//开始尝试打印
for(int i=0;i<n;++i){
for(int j=0;j<m;++j)
printf("%lld ",row[i]+col[j]-nums[i][j]);
printf("\n");
}
}
十五、**比那名居的桃子(定长滑动窗口/前缀和)


解法1:定长滑动窗口
cpp
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL h[N],s[N];
int n,k;
//滑动窗口 维护一个k长度的区间
int main(){
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>h[i];
for(int i=1;i<=n;++i) cin>>s[i];
//先让前面k-1个进去
int left=1,right=1;//滑动窗口
LL hsum=0,ssum=0,hmax=0,smin=0,begin=0;
for(;right<k;++right){
hsum+=h[right];
ssum+=s[right];
}
for(;right<=n;++left,++right){
hsum+=h[right];
ssum+=s[right];
if(hsum>hmax){//如果快乐值更多 就得更新
begin=left;
hmax=hsum;
smin=ssum;
}
else if(hsum==hmax&&ssum<smin){//如果快乐值一样 羞耻值少 也得更新
begin=left;
smin=ssum;
}
//出窗口
hsum-=h[left];
ssum-=s[left];
}
cout<<begin<<endl;
}
解法2:前缀和
cpp
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
LL h[N],s[N];
int n,k;
//滑动窗口 维护一个k长度的区间
int main(){
cin>>n>>k;
int x;
for(int i=1;i<=n;++i){
cin>>x;
h[i]=h[i-1]+x;
}
for(int i=1;i<=n;++i){
cin>>x;
s[i]=s[i-1]+x;
}
//先让前面k-1个进去
LL hmax=0,smin=0,begin=0;
for(int i=k;i<=n;++i)
if(h[i]-h[i-k]>hmax){
begin=i-k+1;
hmax=h[i]-h[i-k];
smin=s[i]-s[i-k];
}
else if(h[i]-h[i-k]==hmax&&s[i]-s[i-k]<smin){
begin=i-k+1;
smin=s[i]-s[i-k];
}
cout<<begin<<endl;
}
十六、压缩字符串1(双指针)


cpp
class Solution {
public:
string compressString(string param) {
int n=param.size();
if(n<2) return param;
string ret;//处理返回结果
for(int i=0;i<n;){
int j=i+1,count=1;
while(j<n&¶m[j]==param[i]){
++j;
++count;
}
ret+=param[i];
if(count>1) ret+=to_string(count);
i=j;
}
return ret;
}
};
十七、**chika和蜜柑(重写排序)


cpp
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
typedef long long LL;
typedef pair<LL,LL> PLL;
PLL a[N];//酸度和甜度的数组
int n,k;
int main(){
cin>>n>>k;
for(int i=0;i<n;++i) cin>>a[i].first;
for(int i=0;i<n;++i) cin>>a[i].second;
sort(a,a+n,[&](const PLL&a,const PLL&b){
return a.second==b.second?a.first<b.first:a.second>b.second;
});
LL s=0,t=0;
for(int i=0;i<k;++i){
s+=a[i].first;
t+=a[i].second;
}
cout<<s<<" "<<t<<endl;
}
十八、01背包


cpp
class Solution {
public:
int dp[1010]={0};
int knapsack(int V, int n, vector<vector<int> >& vw) {
//体积不超过V的情况下 当前能够装下的最大重量
//dp[i][j]表示从前i个物品选,体积不超过j的最大重量
for(int i=0;i<n;++i)
for(int j=V;j>=vw[i][0];--j)
dp[j]=max(dp[j],dp[j-vw[i][0]]+vw[i][1]);
return dp[V];
}
};
