cf题目记录
773
A题
给定三个坐标
就是让你求两个y相同时x的差,这个y要是最大的y
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct nott{
int x;
int y;
}n[100000];
bool cmp(nott x1,nott x2){
if(x2.y!=x1.y) return x1.y<x2.y;
return x1.x<x2.x;
}
int main(void) {
int t;
cin>>t;
while(t--){
for(int i=1;i<=3;++i){
cin>>n[i].x>>n[i].y;
}
int ans=0;
sort(n+1,n+4,cmp);
// for(int i=1;i<=3;++i) cout<<n[i].x<<" "<<n[i].y<<" ";
// cout<<"\n";
for(int i=1;i<=2;++i){
if(n[i].y==n[i+1].y){
if(i==2) ans=n[3].x-n[2].x;
}
}
cout<<ans<<"\n";
}
return 0;
}
// if(y[1]==y[2]&&y[1]!=0&&y[3]<y[1]) ans=abs(x[1]-x[2]);
// else if(y[1]==y[3]&&y[1]!=0&&y[2]<y[1]) ans=abs(x[1]-x[3]);
// else if(y[2]==y[3]&&y[2]!=0&&y[1]<y[2]) ans=abs(x[2]-x[3]);
// cout<<ans<<endl;
收获:ans我本来定义的是double,因为我看题目输出是浮点数,然后wa了,发现大数相减时,会把后面的省略了,比如
//698826176 540020274
//890345633 540020274
//他输出191519000.0000000000
//而答案应该是191519457.0000000000
然后把double改为int就行了,因为减数和被减数都是int型的
772
B
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e5+10;
int a[N],ans[N];
int main(void) {
int t,n;
cin>>t;
while(t--){
cin>>n;
fill(ans,ans+n+1,0);
int k=0,sum=0;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=2;i<=n-1;++i){
if(a[i]>a[i-1]&&a[i]>a[i+1]) {
ans[++k]=i;
sum++;
}
}
for(int i=1;i<=k;++i){
if(i==k) a[ans[k]]=max(a[ans[k]-1],a[ans[k]+1]);
if(ans[i+1]-ans[i]==2) {
a[ans[i]+1]=max(a[ans[i]],a[ans[i+1]]);
sum--;
i++;
}
else a[ans[i]]=max(a[ans[i]-1],a[ans[i]+1]);
}
cout<<sum<<endl;
for(int i=1;i<=n;++i) cout<<a[i]<<" ";
cout<<endl;
}
return 0;
}
A题
题意 如果两个数字或运算与原数或运算相当,则可以用这两个数代替原来的数,问经过一系列操作后,数字总和最小是多少
思路:把所有数或运算一遍即可得到答案,因为如果是1,肯定不能通过操作改变这个1,只有两个都是1才能通过操作把其中一个1变为0使得结果保持不变
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=2e5+10;
int a[N];
int main(void) {
int t,n;
cin>>t;
while(t--){
cin>>n;
int ans=0;
for(int i=1;i<=n;++i) {
cin>>a[i];
ans=ans|a[i];
}
cout<<ans<<endl;
}
return 0;
}
122 B题
01串的问题,哪个个数少删掉哪个,求能删掉的最大个数
思路:如果字符串中0和1的数量不相等,删掉最少的个数,如果相等 则只能删掉原有的个数减1
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
const int N=2e5+10;
char str[N];
int main(void) {
int n;
cin>>n;
while(n--){
cin>>str;
int sum1=0,sum2=0;
int len=strlen(str);
for(int i=0;i<len;++i){
if(str[i]=='0') sum1++;
else sum2++;
}
if(sum1==sum2) cout<<sum1-1<<endl;
else cout<<min(sum1,sum2)<<endl;
}
return 0;
}
126
B
就是给你一个数字,两个操作,
n=(n+1)%32768或n=(n*2)%32768
问变到0所需的最小操作数
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
queue<int>q;
const int mod = 32768;
const int N = 2e5 + 10;
int dis[N],ch[N];
void bfs() {
int u;
while (!q.empty()) q.pop();
memset(dis, 0, sizeof(dis));
q.push(mod);
dis[mod] = 1;
dis[0] = 1;
while (!q.empty()) {
u = q.front();
//cout << u << " ";
q.pop();
if (!dis[u - 1]) {
dis[u - 1] = dis[u] + 1;
q.push(u - 1);
}
if ((!dis[u / 2]) && (u % 2 == 0)) {
dis[u / 2] = dis[u] + 1;
q.push(u / 2);
}
if ((!dis[(u + mod)/2]) && ((u + mod) % 2 == 0)) {
dis[(u + mod)/2] = dis[u] + 1;
q.push((u + mod)/2);
}
}
}
int main(void) {
int n;
cin >> n;
bfs();
for (int i = 1; i <= n; ++i) {
cin >> ch[i];
}
for (int i = 1; i <= n; ++i) {
cout << dis[ch[i]] - 1 << " ";
}
return 0;
}
这种做法是把32768先放到队列中,然后倒推
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <map>
#include <cstring>
#include <queue>
using namespace std;
queue<int>q;
const int mod = 32768;
const int N = 1e6 + 10;
int dis[N];
int ch[N];
int main(void) {
int a, x;
cin >> x;
for (int i = 1; i <= x; ++i) {
cin >> a;
while (!q.empty()) q.pop();
memset(dis, 0x3f, sizeof(dis));
dis[a] = 0;
q.push(a);
while (!q.empty()) {
int u = q.front();
q.pop();
if ((u + 1) == mod) {
dis[u + 1] = dis[u] + 1;
break;
}
if (u*2 == mod ) {
dis[u * 2] = dis[u] + 1;
break;
}
if ( dis[(u+1)%mod] == 0x3f3f3f3f) {
dis[(u+1)%mod] = dis[u] + 1;
q.push((u+1)%mod);
}
if ( dis[(u*2)%mod] == 0x3f3f3f3f) {
dis[(u *2)%mod ] = dis[u] + 1;
q.push((u*2)%mod);
}
}
cout << dis[32768]<<" ";
}
return 0;
}
这是正着写的做法,但是TLE,因为很多组数据嘛,而我是每输入一个进行一个操作,显然没有刚才把所有的答案先初始化好来的快
大二题目记录
day1A题
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,c1,c2,v,t;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int stair[N],ele[N];
void solve(){
int x1,x2,y1,y2;
int sum;
cin>>n>>m>>c1>>c2>>v;
for(int i=1;i<=c1;++i) cin>>stair[i];
for(int i=1;i<=c2;++i) cin>>ele[i];
sort(stair+1,stair+c1+1);//上面的输入下标决定是否要加1
sort(ele+1,ele+c2+1);
cin>>t;
while(t--){
int ans=inf;
int b,d;
cin>>x1>>y1>>x2>>y2;
if(x1==x2) cout<<abs(y1-y2)<<endl;
else{
if(stair[1]!=0){
int a=lower_bound(stair+1,stair+c1+1,y1)-stair;//这里要减去首地址
if(a>1) {
b=a-1;
sum=abs(stair[b]-y1)+abs(x2-x1)+abs(stair[b]-y2);
ans=min(ans,sum);
}
sum=abs(stair[a]-y1)+abs(x2-x1)+abs(stair[a]-y2);
ans=min(ans,sum);
}
if(ele[1]!=0){
int c=lower_bound(ele+1,ele+c2+1,y1)-ele;
if(c>1){
d=c-1;
sum=abs(ele[d]-y1)+ceil(1.0*abs(x2-x1)/v)+abs(ele[d]-y2);
ans=min(ans,sum);
}
sum=abs(ele[c]-y1)+ceil(1.0*abs(x2-x1)/v)+abs(ele[c]-y2);
ans=min(ans,sum);
}
cout<<ans<<endl;
}
}
}
int main(void) {
solve();
return 0;
}
收获:1:sort排序和二分查找这两个知识点,而且括号里的参数容易错,二分返回的是地址,如果要是下标记得减去数组
2:刚开始用暴力遍历,显然TLE,然后就要想到最近的肯定就是只有那四种可能,然后比较那四种可能就行了
3:特殊情况没考虑到:比如说在同一层时,需要特判,比如没有电梯或楼梯时
训练赛题目
第一次天梯赛
7-12 哲哲打游戏
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N=1e5+10;
vector<int>ch[N];
int ans[N];
int main(void) {
int t,n,m,now=1;
int x,y,h;
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>t;
for(int j=1;j<=t;++j){
//cin>>ch[i][j];
cin>>h;
ch[i].push_back(h);//怎么存进去
}
}
int i=1;
while(m--){
cin>>x>>y;
if(x==0) now=ch[now][y-1];//这里是y-1
else if(x==1) {
cout<<now<<endl;
ans[y]=now;
}
else if(x==2) now=ans[y];
}
cout<<now;
return 0;
}
my reward:
1.首先我开二维数组,爆了,所以这时要用vector来搞数组,csdn说一般二维数组每一维不超过1e4
2.vector的用法,存数据用push_back,在找数组元素的时候,注意他的第二维是从0开始的,所以上面的代码是y-1
刚开始我就写成了y,然后读数据的时候就直接读到一半就卡在那里了
7-10 病毒溯源
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N=1e4+10;
int book[N],a[N],b[N];
vector<int>g[N];
int maxx=-1;
void dfs(int x,int step){
int len=g[x].size();
if(len==0){
if(step>maxx){
maxx=step;
for(int i=0;i<step;++i)
b[i]=a[i]; //输出路径?为什么要再设个b数组
}
return ;
}
for(int i=0;i<len;++i){
a[step]=g[x][i];//用于记录路径的
dfs(a[step],step+1);
}
}
int main(void) {
int n,t,x,j;
cin>>n;
for(int i=0;i<n;++i){
cin>>t;
for(int k=1;k<=t;++k){
cin>>x;
book[x]=1;//和拓扑排序那个入度差不多,肯定要找入度为0的作为起始点
g[i].push_back(x);
}
sort(g[i].begin(),g[i].end());//啊啊啊啊 因为优先筛选小的序列
}
for(int i=0;i<n;++i){
if(book[i]==0) {
j=i;
break;
}
}
a[0]=j;//
dfs(j,1);
cout<<maxx<<endl;
for(int i=0;i<maxx;++i){
if(i==maxx-1) cout<<b[i];
else cout<<b[i]<<" ";
}
return 0;
}
my reward
1.那个sort的那个排序,为了确保优先筛选小的序列,很巧妙欸,而且也不知道vector也能这样排序的,用begin和end
2.dfs记录路径的问题,
7-6 吉老师的回归
#include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=1e4+10;
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0);
int n,t,sum=0,flag=1;
string s;
string s1="qiandao",s2="easy";
cin>>n>>t;
getline(cin,s);
//getchar();这里用这个就不行,真奇怪
for(int i=1;i<=n;++i){
getline(cin,s);
if(s.find(s1)!=s.npos) continue;//上下两行是等价的,看下面的reward,找不到有两种返回值???
if(s.find("easy")!=-1) continue;
if(sum==t) {
cout<<s;
flag=0;
sum++;
}
else sum++;
}
if(flag) cout<<"Wo AK le";
return 0;
}
my reward:
1.查找字符串怎么找,
find函数,如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string::npos,
find()函数的用法,会找到匹配的字符串,找到返回第一次出现的首地址,找不到则返回-1
函数里面可以是具体的字符值,也可以是变量。我比赛时写的是循环遍历一个一个字母找,真的弱智,
2.关闭同步流的操作,那两行缺一不可,否则输出的答案就不会在最后面了
3.为什么getchar不行,必须要用getline呢,数字与字母之间
7-11 清点代码库
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
map<vector<int>, int>mp;
const int N = 1e5 + 10;
int ch[N];
int main(void) {
int n, m;
int x;
cin >> n >> m;
mp.clear();
vector<int>v(m);
for (int i = 1; i <= n; ++i) {
v.clear();
for (int j = 1; j <= m; ++j) {
cin >> x;
v.push_back(x);
}
mp[v]++;
}
cout << mp.size() << "\n";
//从大到小找,找mp的第二维,有的话就输出,然后两个测试点超时了
for (int i = n; i >= 1; --i) {
//是这层循环太复杂了,因为每次找mp的第二维都要从头开始找,所以要怎么办呢
//然后就要想到用vector来存取mp里的值,每次找mp的第二维的时候,可以直接通过下标来访问,就不用循环啦
for (auto t : mp) {
if (t.second == i) {
cout << i;
for (auto x : t.first) {
cout << " " << x;
}
cout << "\n";
}
}
}
return 0;
}
//#include <stdio.h>
//#include <iostream>
//#include <vector>
//#include <map>
//#include <algorithm>
//using namespace std;
//const int N=1e4+10;
//map<vector<int>,int>mp;
//vector<vector<int> >v[N];
//int main(void) {
//int n,m;
//int ans=0;
// cin>>n>>m;
// for(int j=1;j<=n;++j){
// vector<int>g(m);
// for(int i=0;i<m;++i){//这里要从0开始哦
// cin>>g[i];
// }
// mp[g]++;
// }
// for(auto t:mp){
// v[t.second].push_back(t.first);
// ans++;
// }
// cout<<ans<<endl;
// for(int i=n;i>=1;--i){
// for(auto t:v[i]){
// cout<<i;
// for(auto a:t) { //敲重点哦,输出数组元素还要再开个循环
// cout<<" "<<a;
// }
// cout<<endl;
// }
// }
//return 0;
//}当我map存了数组和对应的个数时,想要输出,却没有什么好办法
怎么想到用vector的
#include <bits/stdc++.h>
using namespace std;
map<vector<int>,int>mp;
const int N=1e4+10;
//vector<int,vector<int> >vxx;
vector<vector<int> >vxx[N];//为什么要V[N]呢 不能是V 因为下面 vxx[t.second].push_back(t.first)
int main(void){
int n,m,ans=0;
cin>>n>>m;
for(int j=1;j<=n;++j){
vector<int>v(m);//这个一定要写这里,放最上面就寄了,因为每次循环不可能把vector原有的删了
for(int i=0;i<m;++i){
cin>>v[i];//经过实验发现,如果这里写的是cin>>x; v[i].push_back(x) 在数组的前面会多出三个0,因为样例给的m是3,然后vector开辟三个数组,并且都初始化为0,所以push_back就会在他之后加上元素。解决办法就是每次clear一下就行啦
}
mp[v]++;
}
for(auto t: mp){
vxx[t.second].push_back(t.first);//个数作为下标,便于下面循环,你看下面循环的i值是从大到小的
ans++;
}
cout<<ans<<endl;
for(int i=n;i>=1;--i){
for(auto t:vxx[i]){//如果没有元素的话,就不会循环,所以不需要用if来判断
cout<<i;
for(auto x:t) {
cout<<" "<<x;
}
cout<<endl;
}
}
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXSizD6E-1690427959413)(C:\Users\14716\AppData\Roaming\Typora\typora-user-images\image-20220409113150190.png)]
第二次天梯赛
7-13 那就别担心了
#include <bits/stdc++.h>
using namespace std;
vector<int>v[510];
int way[510];
int flag=1;
int dfs(int s){
if(way[s]>0) return way[s];
if(v[s].size()==0) flag=0;
//这样写也是对的
// for(int i=0;i<v[s].size();++i){
// way[s]+=dfs(v[s][i]);
// }
//atuo错误教学
//for(auto t: v[s]){
// way[s]+=dfs(v[s][t]);
//}
for(auto t: v[s]){
way[s]+=dfs(t);//这里容易错
}
return way[s];
}
int main(void) {
int n,m,x,y,start,fina;
cin>>n>>m;
while(m--){
cin>>x>>y;
v[x].push_back(y);
}
cin>>start>>fina;
way[fina]=1;
cout<<dfs(start)<<" ";
if(flag) cout<<"Yes";
else cout<<"No";
return 0;
}
think:dfs加记忆化搜索,把终点值记为1,假如到头了却没经过终点,flag=0
第三次天梯赛
7-11 深入虎穴
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N=1e5+10;
vector<int>g[N];
char str[101];
int ru[N];
int maxx=0,ans=0;
void dfs(int s,int step){
if(g[s].size()==0) {
if(step>maxx) {
maxx=step;
ans=s;
}
return;//return 有没有貌似影响不大
}
for(int i=0;i<g[s].size();++i){//敲重点,是00000000
dfs(g[s][i],step+1);
}
}
int main(void) {
int n,t,x;
cin>>n;
for(int i=1;i<=n;++i){
cin>>t;
while(t--){
cin>>x;
g[i].push_back(x);
ru[x]++;
}
}
for(int i=1;i<=n;++i){
if(ru[i]==0){
dfs(i,1);//如果写成0有个样例过不了
break;
}
}
cout<<ans;
return 0;
}
think:比赛时没有想到入度,直接dfs(1,0)去了,还有一个地方是在循环遍历的时候,写成1了,敲重点!!!!
如果写成1了,就不可能对
#include <bits/stdc++.h>
#include <cstring>
using namespace std;
int main(void){
string str;
int j;
getline(cin,str);//读取一整行
//int len=str.size();
// int len=str.length();
for(int i=0;i<str.size();++i){///1111
if(str[i]=='6'){
for( j=i+1;j<str.size()&&str[j]=='6';j++);//222222
if(j-i>3&&j-i<=9) str.replace(i,j-i,"9");
else if(j-i>9) str.replace(i,j-i,"27");
// for( j=1;i+j<str.size()&&str[i+j]=='6';++j);
// if(j>9) str.replace(i,j,"27");
// else if(j>3) str.replace(i,j,"9");
}
}
cout<<str<<endl;
return 0;
}
reward:字符串操作replace的用法,还有整行读取的使用,pta不支持gets,比赛时用gets编译都过不了
还有一个问题就是,定义一个len放在循环判断里面不太行,单独放在1或者2没问题,同时放上去就不行,不知道为什么
第四次天梯赛
7-11 名人堂与代金券
#include <bits/stdc++.h>
#include <stack>
#include <cstring>
using namespace std;
struct people{
char name[50];
int num;
}p[10002];
bool cmp(struct people x,struct people y){
if(x.num==y.num) return strcmp(x.name,y.name)<0?1:0; //排名并列时,按账号的字母序升序输出。
return x.num>y.num;//降序排序
}
int main(){
int n,x,num;
int sum=0;
cin>>n>>x>>num;
for(int i=1;i<=n;++i){
scanf("%s %d",p[i].name,&p[i].num);
if(p[i].num>=x) sum+=50;
else if(p[i].num>=60) sum+=20;
}
printf("%d\n",sum);
sort(p+1,p+1+n,cmp);
//for(int i=1;i<=n;++i){
// printf("%d %s %d\n",i,p[i].name,p[i].num);
//}
int paiming=1,ayy=0;
for(int i=1;i<=n-1;++i){
if(p[i].num==p[i+1].num){
printf("%d %s %d\n",paiming,p[i].name,p[i].num);
ayy++;
}
else {
printf("%d %s %d\n",paiming,p[i].name,p[i].num);
paiming=paiming+ayy+1;
ayy=0;
if(paiming>num) break;
}
}
if(paiming<=num) printf("%d %s %d\n",paiming,p[n].name,p[n].num);
return 0;
}
结构体排序
7-10 小字辈
#include <bits/stdc++.h>
#include <vector>
using namespace std;
vector<int>g[100100];
vector<int>ans;
int maxx=0;
int a;
void dfs(int x,int step){
if(g[x].size()==0){
if(step>maxx) {
maxx=step;
ans.clear();
ans.push_back(x);
}
else if(step==maxx) ans.push_back(x);//else
}
for(int i=0;i<g[x].size();++i){
dfs(g[x][i],step+1);
}
}
int main(void){
int n,x;
cin>>n;
for(int i=1;i<=n;++i) {
cin>>x;
if(x==-1) a=i;
else //else
g[x].push_back(i);
}
dfs(a,1);//dfs(-1,0)不行,因为是数组,下标不可能为-1
printf("%d\n",maxx);
sort(ans.begin(),ans.end());
printf("%d",ans[0]);
for(int i=1;i<ans.size();++i)
printf(" %d",ans[i]);
return 0;
}
牛客浙农林
瓜瓜的01串
#include <bits/stdc++.h>
using namespace std;
int main(void){
int n,k,sum1=0,sum0;
int ans=0;
cin>>n>>k;
string str;
cin>>str;
int len=str.size();
for(int i=0;i<len;++i){
if(str[i]=='1') sum1++;
}
//如果没有执行操作1
//操作2和sum1的个数有关,如果操作数有多,并且是偶数,那么只要重复实现操作二在同一个字符上即可,
if(k<sum1) ans=max(ans,n-(sum1-k));
else ans=max(ans,n-(k-sum1)%2);
//如果执行了操作1,那么k就要减个1,这时和sum0有关
//如果操作数有多,那么只要重复实现操作一即可
if(k>=1){
k--;
sum0=n-sum1;
if(k<sum0) ans=max(ans,n-(sum0-k));
else ans=max(ans,n-(k-sum0)%2);
}
cout<<ans;
return 0;
}
因为偶数次的操作1等于没操作,所以操作1就可以转化成1次和0次。所以就分两种情况,一是执行了操作一的,另一个是没执行操作一的,然后两种情况取最值就行
策策学长找py
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct peo{
int x;
int y;
}s[N];
bool cmp(peo x1,peo x2){
if(x1.x==x2.x) return x1.y<x2.y?1:0;
return x1.x<x2.x;
}
int main(void){
int t,n,m,k;
cin>>t;
while(t--){
cin>>n>>m>>k;
for(int i=1;i<=k;++i){
scanf("%d%d",&s[i].x,&s[i].y);
}
int flag=1;
sort(s+1,s+k+1,cmp);
for(int i=1;i<=k-1;++i){
if(s[i].y>s[i+1].y){
cout<<"NO"<<'\n';
flag=0;
break;
}
}
if(flag) cout<<"YES"<<'\n';
}
return 0;
}
我一开始用dfs,后来用dp,寄,建议以后写之间看看内存和时间
因为只能往右和往下走,所以考虑把他们的x进行排序,然后看y是不是升序即可(等于也可以),如果是,就yes
牛客上海理工
链接:https://ac.nowcoder.com/acm/contest/31389/D
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
int f[50];
const int mod=1e9+7;
signed main(void) {
int n,k;//n代表第几项,k代表倍数;
cin>>n>>k;
int sum=0;
f[0]=1;
f[1]=k;
for(int i=2;i<=35;++i) f[i]=f[i-1]*k%mod;
for(int i=31;i>=0;i--){ //i从32开始就寄了
if(n&(1<<i)) {
sum=(sum+f[i])%mod;
cout<<i<<" ";
}
}
cout<<sum;
return 0;
}
感觉像是思维题,想的到用位运算就比较简单
天气预报
最近天上总会莫名其妙地下箭毒蛙,这太危险了,因此他只能在晴天出门,下箭毒蛙的日子就只能待在家休息,因此他查了查天气预报(Weather Report\textit{Weather Report}Weather Report),未来nnn天内的天气结果可以用一个长度为nnn的字符串表示,其中000表示晴朗,111表示会下箭毒蛙。Komorebi希望在这nnn天中选择连续\textbf{连续}连续的一段时间,也可以一天都不选,使得他在这段时间内至少可以出去玩aaa天,并且至少在家休息bbb天。
那么他一共有几种选法呢?
双指针的做法
//TLE的做法
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int n,a,b,ans=0;
string str;
cin>>n>>a>>b;
getchar();
getline(cin,str);
for(int i=0;i<n;++i){
int sum0=0,sum1=0;
for(int j=i;j<n;++j){
if(str[j]=='0') sum0++;
if(str[j]=='1') sum1++;
if(sum0>=a&&sum1>=b) {
ans=ans+n-j;
break;
}
}
}
if(!a&&!b) ans++;
cout<<ans;
return 0;
}
//所以时间复杂度怎么算,怎么感觉和我上面的复杂度差不多
//还有一种做法就是i往后移的时候,j不可能往前移的,即左边界往右移的时候,右边界不可能往左移
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int cnt[N];
int n,a,b,ans=0;
int check(int l,int r){
int sum1=cnt[r]-cnt[l-1];
int sum0=(r-l+1)-sum1;
if(sum1>=b&&sum0>=a) return 1;
return 0;
}
signed main(){
string str;
//cin>>n>>a>>b;
scanf("%d%d%d",&n,&a,&b);
getchar();
getline(cin,str);
cnt[0]=str[0]-'0';
for(int i=1;i<n;++i){
cnt[i]=cnt[i-1]+str[i]-'0';
}
int ans=0;
for(int i=0,j=0;i<n;++i){
while(j<n&&!check(i,j)) j++;
while(j<=n&&j<i) j++; //为什么int j=i 然后把这一行删掉不行呢
//上面两行交换顺序并无大碍
if(check(i,j)==1&&j<n) ans=ans+n-j;
}
if(!a&&!b) ans++;
//cout<<ans;
printf("%lld",ans);
return 0;
}
次佛锅
你好阿,穿越题目前来的选手
众所周知backordinary不会次佛锅,所以邀请您来喂他。
佛锅是一串包含大小写英文字母、数字、空格的字符串。每个食材用单词加数字的方式表示,代表这个食材有多少个,例如yaxin 1代表有1个yaxin。每个食材间用空格隔开,相同食材可能多次出现。
backordinary每次会告诉你他想吃啥,需要你去锅里给他夹出来,他想知道每次他能吃到多少。
#include <bits/stdc++.h>
#include <map>
#include <cstring>
using namespace std;
map<string,int>mp;
int main(void){
string str;
getline(cin,str);
int len=str.size();
for(int i=0;i<len;++i){
int sum=0;
string ans="";
//判断是否是数字有一个函数的,isdigit
if(str[i]!=' '&&isdigit(str[i])==0){
while(str[i]!=' '&&isdigit(str[i])==0){
ans=ans+str[i];//字符串相加的操作
i++;
}
}
if(str[i]==' ') i++;
while(isdigit(str[i])){
sum=sum*10+(str[i]-'0');
i++;
}
//cout<<ans<<sum<<"\n";
mp[ans]=mp[ans]+sum;
}
int n;
string ss;
cin>>n;
while(n--){
cin>>ss;
cout<<mp[ss]<<"\n";
}
return 0;
}
高级操作
#include <bits/stdc++.h>
using namespace std;
map<string, int>mp;
int main(void){
while(cin.peek()!='\n'){
string s;
int num;
cin>>s>>num;
mp[s]=mp[s]+num;
}
int n;
string str;
cin>>n;
while(n--){
cin>>str;
cout<<mp[str]<<"\n";
}
}
peek()
-
此函数返回输入流中的下一个字符,但是并不将该字符从输入流中取走——相当于只是看了一眼下一个字符,因此叫 peek。
-
cin.peek() 不会跳过输入流中的空格、回车符。在输入流已经结束的情况下,cin.peek() 返回 EOF。
-
在输入数据的格式不同,需要预先判断格式再决定如何输入时,peek() 就能起到作用。
-
cin.peek()的返回值是一个char型的字符,其返回值是指针指向的当前字符,但它只是观测
指针停留在当前位置并不后移;如果要访问的字符是文件结束符,则函数值是EOF(-1)cin.peek()的返回值是一个char型的字符,其返回值是指针指向的当前字符,但它只是观测
指针停留在当前位置并不后移;如果要访问的字符是文件结束符,则函数值是EOF(-1)
cin.get()用来从指定的输入流中提取一个字符(包括空白字符),
函数的返回值就是读入的字符。若遇到输入流中的文件结束符,
则函数值返回文件结束标志EOF(End Of File),一般以-1代表EOF
叠硬币
Komorebi最近迷上了叠硬币的游戏。他先放一枚硬币在桌上,然后一枚一枚地往上堆,看能最多放几枚而不倒。
随着不断训练,Komorebi的技术也不断精进,但由于这样玩很费时间,很快他厌倦了这样的玩法。于是他想出了另一种玩法,先把硬币堆成一个个小堆,然后再把这些小堆叠起来,看最多能叠多高。
玩着玩着,Komorebi突发奇想:对于n个硬币堆,如果想选取一些硬币堆,一堆一堆地叠起来,将它们叠到正好H个硬币那样高(不可以随意增加或减少每个硬币堆的硬币数量),最少需要几个硬币堆呢?由于硬币堆太多了,他有些糊涂了,请你帮帮他吧!
第一行输出一个正整数m,表示达到高度H的最少硬币堆数。下面输出m个数代表该硬币堆的高度,并且方案按高度升序输出。如果有多个满足要求的方案(且都已按高度升序排列),则输出字典序最小的那个方案(如有两个长度都为m的序列A和B,若Ai=BiA_i=B_iAi=Bi,i=1,2,3,…,s(s<m)i=1,2,3,\ldots,s\left(s<m\right)i=1,2,3,…,s(s<m),且Ai+1<Bi+1A_{i+1}<B_{i+1}Ai+1<Bi+1,则认为序列A按字典序小于序列B)。如果没有任何一种方案可以正好达到高度H,就输出-1
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int dp[3009][3009];
int a[N],ans[N];
int main(void){
int m,h;
cin>>m>>h;
for(int i=1;i<=m;++i) cin>>a[i];
sort(a+1,a+m+1);
memset(dp,127,sizeof(dp));//0x3f3f3f3f的每个字节都是0x3f!所以要把一段内存全部置为无穷大,我们只需要memset(a,0x3f,sizeof(a))即可,实验了一下,发现写0x3f3f3f3f也是一样的,是1061109567,而写127,是2139062143
dp[0][0]=0;
for(int i=1;i<=m;++i){
dp[i][0]=0;
for(int j=0;j<=h;++j){
dp[i][j]=dp[i-1][j];
if(j>=a[i]) dp[i][j]=min(dp[i][j],dp[i-1][j-a[i]]+1);
}
}
//首先裸的dp要会写,初始化为0x3f3f3f3f,还有循环怎么写,循环内的初始化,都要会哦
if(dp[m][h]>=0x3f3f3f3f) cout<<-1;
else {
cout<<dp[m][h]<<"\n";
int j=1;
//从最大的开始找,类似于贪心,使他字典序最小
for(int i=m;i>=1;i--){
if(a[i]<=h&&dp[i-1][h-a[i]]+1==dp[i][h]) {
ans[j++]=a[i];
h=h-a[i];
}
}
for(int i=j-1;i>=1;--i) cout<<ans[i]<<" ";
}
}
//把dp变成一维数组的做法
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int dp[3009];
int a[N],ans[N];
int main(void){
int m,h;
cin>>m>>h;
for(int i=1;i<=m;++i) cin>>a[i];
sort(a+1,a+m+1);
memset(dp,127,sizeof(dp));
dp[0]=0;
for(int i=1;i<=m;++i){
for(int j=h;j>=a[i];--j){
dp[j]=min(dp[j],dp[j-a[i]]+1);
}
}
if(dp[h]>=0x3f3f3f) cout<<-1;
else {
cout<<dp[h]<<"\n";
int j,k=1;
for(int i=1,j=h;i<=m;++i){
if(dp[j-a[i]]+1==dp[j]) {
ans[k++]=a[i];
j=j-a[i];
}
}
for(int i=1;i<k;++i) cout<<ans[i]<<" ";
}
}
浙大训练赛
题目大意:给你一些字符串,两两连接,问能连接成”BSUIROPENX“的有几种方案
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <cstring>
using namespace std;
#define int long long
map<string,int>mp;
map<string,string>mpp;
set<string>ans;
signed main(void) {
int n;
string str="BSUIROPENX",s;
int len=str.size();
string ss="";
for(int i=0;i<len-1;++i){
ss=ss+str[0];
str.erase(str.begin());
mpp[ss]=str;
}
//for(auto t:mpp){
// cout<<t.first<<" "<<t.second<<"\n";
//}
scanf("%d",&n);
for(int i=1;i<=n;++i){
cin>>s;
mp[s]++;
}
int ans=0;
for(auto t:mp){
ans=ans+t.second*mp[mpp[t.first]];
}
cout<<ans;
return 0;
}
题目大意:
给定两个字符串,让你求一个字符串,满足这个字符串删掉一个字符后可以变成给定的两个字符串,如果不存在,输出impossible
#include <iostream>
#include <cstring>
using namespace std;
void solve() {
string a, b;
cin >> a >> b;
if (a == b) {
cout << a << 'a';
return ;
}
int l = 0, r = a.size() - 1;
while (a[l] == b[l]) l++;
while (a[r] == b[r]) r--;
if (a.substr(l + 1, r - l) == b.substr(l, r - l)) {
//a.insert(a.begin()+ r + 1, b[r]);
//cout << a;
cout << a.substr(0, r + 1) + b.substr(r, 1) + a.substr(r + 1);//第二个参数不写,表示截取到末尾
return ;
}
swap(a, b);
if (a.substr(l + 1, r - l) == b.substr(l, r - l)) {
//a.insert(a.begin() + r + 1, b[r]);
//cout << a;
cout << a.substr(0, r + 1) + b.substr(r, 1) + a.substr(r + 1);
return ;
}
cout << "IMPOSSIBLE";
}
int main(void) {
solve();
return 0;
}
2021浙江省赛 J. Grammy and Jewelry(完全背包+最短路(Dijkstra))
题目大意:给定n个顶点,m条边,时间t,然后每个顶点都有无限多的宝石,宝石的价值为a[i],然后每去一条边消耗的时间为1,从顶点1出发,要把宝石带回顶点才算获得该价值,问在t的时间里面,能获得的最大价值是多少
//这是我Dijkstra的板子
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 5e5+10;
const int inf = 0x3f3f3f3f;
struct node{
int to,w;
};
int m,n,s;
vector<node>g[maxn];
int dis[maxn];
bool vis[maxn];
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
void Dijkstra(){
for(int i=1;i<=n;i++){
vis[i]=false;
dis[i]=inf;
}
dis[s]=0;
q.push(make_pair(dis[s],s));
while(!q.empty()){
pair<int,int> now =q.top();
q.pop();
if(vis[now.second]) continue;
vis[now.second]=true;//如果已经被访问过了就continue因为是优先队列,所以保证了先访问的一定是最短的,即已经求出了到某点的最短路径,队列剩下的都不是最短的了,continue即可
for(int i=0;i<g[now.second].size();i++){
//now.second->g[now.second][i].to
int to=g[now.second][i].to;
int w=g[now.second][i].w;
if(dis[to]>dis[now.second]+w){
dis[to]=dis[now.second]+w;
q.push(make_pair(dis[to],to));
}
}
}
}
int main(void) {
scanf("%d%d%d",&n,&m,&s);//代表有n个顶点,m条边,问从s到每个顶点的最短路
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);//从u到v的距离是w
g[u].push_back((node){v,w});//这里加了node()在vs上编译通不过,不过在dev上可以
}
Dijkstra();
for(int i=1;i<=n;i++) printf("%d ",dis[i]);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 5e5+10;
const int inf = 0x3f3f3f3f;
int dp[maxn];
struct node{
int to,w;
};
int m,n,s;
int t;
int a[maxn];
vector<node>g[maxn];
int dis[maxn];
bool vis[maxn];
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
void Dijkstra(){
for(int i=1;i<=n;i++){
vis[i]=false;
dis[i]=inf;
}
dis[1]=0;//顶点默认是1
q.push(make_pair(dis[1],1));
while(!q.empty()){
pair<int,int> now =q.top();
q.pop();
if(vis[now.second]) continue;
vis[now.second]=true;//如果已经被访问过了就continue因为是优先队列,所以保证了先访问的一定是最短的,即已经求出了到某点的最短路径,队列剩下的都不是最短的了,continue即可
for(int i=0;i<g[now.second].size();i++){
//now.second->g[now.second][i].to
int to=g[now.second][i].to;
int w=g[now.second][i].w;
if(dis[to]>dis[now.second]+w){
dis[to]=dis[now.second]+w;
q.push(make_pair(dis[to],to));
}
}
}
}
int main(void) {
scanf("%d%d%d",&n,&m,&t);
for (int i = 2; i <= n ; ++i) scanf("%d", &a[i]);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d",&u,&v);
if (u == v) continue;
g[u].push_back({v,2});//因为是来回,边权是2
g[v].push_back({u,2});//这是无向图
}
Dijkstra();
//for(int i=1;i<=n;i++) printf("%d ",dis[i]);
//下面就是完全背包问题
for (int i = 1; i <= n; ++i) {
for (int j = dis[i]; j <= t; ++j) {
dp[j] = max(dp[j], dp[j - dis[i]] + a[i]);
}
}
for (int i = 1; i <= t; ++i) {
cout << dp[i] << " ";
}
return 0;
}
leetcode
6128
思路,首先遍历suits,如果有两个不同就退出,如果全部相同return FLush
然后用map存数字,再遍历map记录maxx(出现的数字的最大次数)
class Solution {
public:
string bestHand(vector<int>& ranks, vector<char>& suits) {
int flag =1 ;
for(int i=0;i<suits.size()-1;++i){
if(suits[i]!=suits[i+1]) {
flag=0;
break;
}
}
if(flag==1) return "Flush";
map<int,int>mp;
for(int i=0;i<ranks.size();++i){
mp[ranks[i]]++;
}
int maxx=0;
for(auto t:mp){
if(t.second>maxx) maxx = t.second;
}
if(maxx>=3) return "Three of a Kind";
else if(maxx>=2) return "Pair";
else return "High Card";
}
};
6129
class Solution {
public:
long long zeroFilledSubarray(vector<int>& nums) {
int cnt = 0;
long long ans=0;
int size = nums.size();
long long dp[100010]={0};//记录每个0对答案的贡献
for(int i=1;i<=size;++i){
dp[i]=dp[i-1]+i;
// cout<<dp[i];
}
for(int i=0;i<size;++i){
if(nums[i]!=0){
ans=ans+dp[cnt];
cnt=0;
// printf("%d\n",ans);
}
else cnt++;
}
if(cnt!=0) ans=ans+dp[cnt];
return ans;
}
};
6130
class NumberContainers {
public:
map<int,int>mp;
NumberContainers() {
}
void change(int index, int number) {
mp[index]=number;
}
int find(int number) {
for(auto t:mp){
if(t.second==number) return t.first;
}
return -1;
}
};
/**
* Your NumberContainers object will be instantiated and called as such:
* NumberContainers* obj = new NumberContainers();
* obj->change(index,number);
* int param_2 = obj->find(number);
*/
2352文章来源:https://www.toymoban.com/news/detail-613820.html
map里面套vector文章来源地址https://www.toymoban.com/news/detail-613820.html
class Solution {
public:
int equalPairs(vector<vector<int>>& grid) {
map<vector<int>,int>v;
int ans = 0;
for(int i=0;i<grid.size();++i){
v[grid[i]]++;
}
for(int i=0;i<grid.size();++i){
vector<int>cnt;
for(int j=0;j<grid.size();++j){
cnt.push_back(grid[j][i]);
}
if(v.count(cnt)) ans=ans+v[cnt];
}
return ans;
}
};
到了这里,关于算法刷题记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!