A 签到时刻
思路:
按题意模拟一遍就可以,注意边界即可
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
void solve(){
int n;
cin>>n;
int res=0,ans=0;
for(int i=0;i<n;i++){
int a,b;
scanf("%d:%d",&a,&b);
if(a>7){
if(a>8){
ans++;
continue;
}
if(b<=5&&b>0)res++;
else if(b>5) ans++;
}
}
cout<<res<<" "<<ans<<endl;
}
int main(){
int t;
cin>>t;
while(t--)solve();
}
B 牛牛的身高
思路:
我的想法直接存字符串,然后将高位先补0,从右往左遍历,找到大于5即将当前值和后面的变为0,然后标记有后面进位的1,最后判断最高位是0就不输出最高位,否则就输出最高位
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
void solve(){
string s;cin>>s;
s="0"+s;
int n=s.size();
int now=0;
per(i,0,n-1){
if(s[i]+now>='5'){
//cout<<i<<endl;
now=1;
rep(j,i,n-1)s[j]='0';
}
else{
s[i]=s[i]+now;
now=0;
}
}
rep(i,0,n-1){
if(i==0){
if(s[i]>'0')cout<<s[i];
}
else cout<<s[i];
}
cout<<endl;
}
signed main(){
int t;cin>>t;
while(t--)solve();
}
C 说谎的机器
思路:
首先我们要理解题意,当所选点不在他给的区间就说明他说谎了,所以我们很容易想到差分,找到重叠区间最小值,然后就是找出现几次和指令条数
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e6+7;
int a[N],s[N];
struct node{
int l,r;
}tr[N];
void cf(int x,int y){
a[x]+=1;
a[y+1]-=1;
}
int main(){
int n,m;
cin>>n>>m;
int l=0;
while(m--){
int op;
cin>>op;
if(op==1){
int x,y;
cin>>x>>y;
cf(x,y);
tr[l]={x,y};
l++;
}
else if(op==2){
int x;
cin>>x;
cf(x,n);
tr[l]={x,n};
l++;
}
else{
int x;
cin>>x;
cf(1,x);
tr[l]={1,x};
l++;
}
}
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
int minx=2e9+7;
for(int i=1;i<=n;i++){
//cout<<s[i]<<" ";
minx=min(minx,s[i]);
}
int num=0,x;
for(int i=1;i<=n;i++){
if(s[i]==minx){
num++;
x=i;
}
}
int s=0;
for(int i=0;i<l;i++){
if(tr[i].r<x||tr[i].l>x)s++;
}
cout<<s<<" "<<num;
}
D 环上食虫
我的思路:二分答案
处理环我们可以直接将数组存两遍,这里-1只会存在所以吃完都不能饱,然后就是二分答案,循环找是否有满足能吃饱的条件下的最大值最小的数
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
const int N = 1e6 + 100;
int a[N];
int b[N];
//二分答案
int n,s;
bool check(int x){
int sum = 0;
for(int i = 1; i <= 2*n; i++){
if(b[i] <= x){
sum += a[i];
if(sum >= s)
return true;
}else
sum = 0;
}
return false;
}
signed main(){
int sum = 0;
cin>>n>>s;
for(int i = 1; i <= n; i++){
int t;cin>>t;
a[i] = a[i + n] = t;
sum += a[i];
}
for(int i = 1; i <= n; i++){
int t;cin>>t;
b[i] = b[i + n] = t;
}
if(sum < s){
puts("-1");
return 0;
}
int l = 1,r = 1e9;
while(l < r){
int mid = (l + r) >> 1;
if(check(mid)){
r = mid;
}else{
l = mid + 1;
}
}
cout<<l;
return 0;
}
思路2:双指针+区间最大值+环形结构处理
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
const int N = 1e6 + 100;
int a[N];
int b[N];
multiset<int>st;
signed main(){
int n,s;cin>>n>>s;
rep(i,1,n){
cin>>a[i];
a[i+n]=a[i];
}
rep(i,1,n){
cin>>b[i];
b[i+n]=b[i];
}
int sum=0,r=0;
int f=0,mn=2e9;
rep(i,1,n){
while(r<2*n&&sum<s){
r++;sum+=a[r];st.insert(-b[r]);
}
if(sum>=s&&r-i+1<=n){
f=1;
mn=min(mn,-(*st.begin()));
}
sum-=a[i];st.erase(st.find(-b[i]));
}
if(f)cout<<mn<<endl;
else cout<<-1<<endl;
}
E 分组求对数和
思路:二分
我们可以将所以数存在vector < int >sum里面排个序用二分找所以可能sum,然后再用vector < int >all[N]记录当前每一组的,然后再将每一组进行排序二分找可能再每一组的答案
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=1e6+10;
const ll INF=2000000000;
const int mod=998244353;
int n,k;
vector<int> all[N],sum;
int cal(vector<int>&s){
sort(s.begin(),s.end());
int ans=0;
for(int i=0;i<s.size();i++){
int res=lower_bound(s.begin()+i+1,s.end(),k-s[i])-s.begin();
res=s.size()-res+1;
ans+=res;
ans%=mod;
}
return ans;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
int s;
cin>>s;
for(int j=1;j<=s;j++){
int x;
cin>>x;
all[i].push_back(x);
sum.push_back(x);
}
}
int ans=0;
ans=cal(sum);
for(int i=1;i<=n;i++){
ans=(ans-cal(all[i])+mod)%mod;
}
cout<<ans;
return 0;
}
F 骑士战胜魔王
思路:动态规划(Q_Q)不会