4261. 孤独的照片
给一个长度为N的字符串,字符串内容为G或H,求长度大于等于3且只含一个H或G的子串个数
我的思路是两次遍历找单独g和单独h的左右两边,但是代码实现很麻烦
y总的还是牛啊,统计左右两边就正向逆向两次遍历,用两个数组存储当前位置左右两边的G和H个数
有个小track,如果不是0就取两数之差,可以max(0,a-b)
#include<iostream>
#include<vector>
using namespace std;
const int maxx = 5e5+1;
int l[maxx],r[maxx];
int main(){
int N;
cin>>N;
string s;
cin>>s;
//先看左边的
for(int i=0,h=0,g=0;i<N;i++){
if(s[i]=='G'){
l[i]=h;
h=0;
g++;
}else{
l[i]=g;
g=0;
h++;
}
}
//再看右边的(逆序来一次)
for(int i=N-1,h=0,g=0;i>=0;i--){
if(s[i]=='G'){
r[i]=h;
h=0;
g++;
}else{
r[i]=g;
g=0;
h++;
}
}
long long res = 0;
//统计
for(int i=0;i<N;i++){
res+=(long long)l[i]*(long long)r[i]+max(0,l[i]-1)+max(0,r[i]-1);
}
cout<<res<<endl;
return 0;
}
3400统计次数
题目吓人,结果看了下是简单题
强行遍历和枚举,顶多达到O(6*1e6)
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
int res = 0;
for(int i=1;i<=n;i++){
int tmp = i;
while(tmp){
int mo = tmp%10;
tmp/=10;
if(mo==k){
res++;
}
}
}
cout<<res<<endl;
return 0;
}
3443学分绩点
c语言入门题
#include<iostream>
using namespace std;
double jidian(int g){
if(g>=90){
return 4.0;
}else if(g>=85){
return 3.7;
}else if(g>=82){
return 3.3;
}else if(g>=78){
return 3.0;
}else if(g>=75){
return 2.7;
}else if(g>=72){
return 2.3;
}else if(g>=68){
return 2.0;
}else if(g>=64){
return 1.5;
}else if(g>=60){
return 1.0;
}else return 0;
}
int xuefen[11];
int main(){
int N;
cin>>N;
int xuefensum = 0;
for(int i=0;i<N;i++){
cin>>xuefen[i];
xuefensum+=xuefen[i];
}
double jidiansum = 0;
for(int i=0;i<N;i++){
int grade;
cin>>grade;
jidiansum+= jidian(grade)*xuefen[i];
}
printf("%.2lf\n",jidiansum/xuefensum);
return 0;
}
4818奶牛大学
用map进行分组并排序,然后从高价开始遍历
这里注意一下 map的反向查找
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxx =1e5;
typedef long long ll;
const ll maxxx=1e12;
int main(){
int N;
map<int,int> m;
cin>>N;
for(int i=0;i<N;i++){
int tmp;
cin>>tmp;
m[tmp]++;
}
ll resTotal = -1;
int resPrice;
int prePerson=0;
for(auto it = m.rbegin();it!=m.rend();it++){
int curPerson = prePerson+it->second;
ll tmpTotal = (ll)it->first*(ll)curPerson;
prePerson=curPerson;
if(tmpTotal>=resTotal){
resTotal=tmpTotal;
resPrice=it->first;
}
}
cout<<resTotal<<" "<<resPrice<<endl;
return 0;
}
4366上课睡觉
先明确总石子数sum是堆数cnt的个数
,然后不知道怎么知道的一个数n有log(n)个约数
然后通过类似尺取的方法从左往右遍历各堆看是否都能凑成sum/cnt个石子
故时间复杂度为O(nlogn)
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxx = 1e5+1;
int arr[maxx];
bool check(int num,int N){
int tmpSum=0;
for(int i=0;i<N;i++){
tmpSum = tmpSum+arr[i];
if(tmpSum>num){
return false;
}else if(tmpSum==num){
tmpSum=0;
}
}
return true;
}
int main(){
int T;
cin>>T;
while(T--){
memset(arr,0,sizeof arr);
int N;
cin>>N;
int sum=0;
int pre = -1;
for(int i=0;i<N;i++){
cin>>arr[i];
sum+=arr[i];
}
if(sum==0){cout<<0<<endl;continue;}
//求可能的堆数
for(int i=sum;i>=1;i--){
if(sum%i==0){
bool res = check(sum/i,N);
if(res){cout<<N-i<<endl;break;}
}
}
}
return 0;
}