A.面包店故事
n-x>=y
void solve(){
int x,y,n;
cin>>x>>y>>n;
if(n-x>=y){
cout<<"YES";
}else{
cout<<"NO";
}
}
B.放课后的故事
注意《一起》
void solve(){
ll n,m,k;
cin>>n>>m>>k;
vector<int> a(n+1);
ll sum = 0;
for(int i = 1;i<=n;i++) cin>>a[i],sum+=a[i];
ll cnt = sum/k;
cout<<min(cnt,m+1);
}
C.异或故事
注意到可以把单独的最后一位的1取出来,所以直接lowbit就行,但特例是2的n次方,因为2的n次方二进制只有一个1,所以不能lowbit,直接x+1和1就行,但n==0的话,可以参考样例给的2 3
int lowbit(int x){
return x&(-x);
}
void solve(){
int n;
cin>>n;
int res = 2;
for(int i = 1;i<=32;i++,res*=2){
if(res==n){
cout<<"1"<<' '<<n+1<<endl;
return ;
}
}
if(n==1){
cout<<"2 3"<<endl;
return ;
}else{
cout<<lowbit(n)<<' '<<n-lowbit(n)<<endl;
}
}
D.构造故事
有点原题的意思,记得牛客之前有一道删去某个可选边可以组成的三角形最大边长,可以证明,组成边长最大值的三条边一定在排序后相邻,所以暴力枚举就行
bool check(int a,int b,int c){
if(a+b>c&&a+c>b&&b+c>a) return true;
else return false;
}
void solve(){
int n;
cin>>n;
vector<ll> a(n);
for(auto &x : a){
cin>>x;
}
sort(a.begin(),a.end());
ll ans = 0;
bool suc = false;
for(int i = 0;i<n-2;i++){
if(check(a[i],a[i+1],a[i+2])) ans = max(ans,a[i]+a[i+1]+a[i+2]),suc = true;
}
if(!suc){
cout<<"-1"<<endl;
}else{
cout<<ans<<endl;
}
}
E.约会故事
这题超级大暴力,有一个坑点是开心的时间可能是跨度23:xx和01:xx,所以可以考虑用24*60的数组去存happytime,原理是差分,因为发现只用到了零点到两点的时间,,再开一个set去存喜欢的饮料,利用count函数去判断喜不喜欢饮料
#include <bits/stdc++.h>
using namespace std;
const int N = 2000;
int t[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i = 1;i<=n;i++){
int a,b,c,d;
scanf("%d:%d %d:%d",&a,&b,&c,&d);
if(a*60+b==c*60+d) {t[0]++;t[24*60]--;}
else if(a*60+b<c*60+d)
{
t[a*60+b]++;
t[c*60+d+1]--;
}
else
{
t[c*60+d]++;
t[24*60]--;
t[0]++;
t[a*60+b+1]--;
}
}
for(int i=1;i<=24*60-1;i++) t[i]+=t[i-1];
set<string> ss;
while(m--)
{
string s;
cin>>s;
ss.insert(s);
}
int q;
cin>>q;
while(q--){
bool suc1 = false;
bool suc2 = true;
int invh,invs;
scanf("%d:%d",&invh,&invs);
int a,b,c,d;
scanf("%d:%d %d:%d",&a,&b,&c,&d);
string drink;
cin>>drink;
if(t[invh*60+invs]&&invh*60+invs<=119) suc1 = true;
if(a*60+b>c*60+d) suc2 = false;
if(ss.count(drink)==0) suc2 = false;
if(!suc1){
cout<<"Loser xqq"<<endl;
}else{
if(!suc2) cout<<"Joker xqq"<<endl;
else cout<<"Winner xqq"<<endl;
}
}
}
F.不是烤串故事
本题卡自然溢出法哈希
二分+字符串哈希,直接开三个哈希数组,s和t本身的哈希,反转之后的s的哈希然后遍历每个反转位的lcp,这一步用二分,本人也很菜,也是看别人的代码
const int P = 13331;
const i64 mod = 1610612741;
void solve()
{
int n;
std::cin >> n;
std::string s, t;
std::cin >> s >> t;
std::vector<i64> p(n + 1), hs(n + 1), rhs(n + 1), ht(n + 1);
p[0] = 1;
for (int i = 0; i < n; i ++) {
p[i + 1] = p[i] * P % mod;
hs[i + 1] = (hs[i] * P + s[i]) % mod;
ht[i + 1] = (ht[i] * P + t[i]) % mod;
}
std::reverse(all(s));
for (int i = 0; i < n; i ++) {
rhs[i + 1] = (rhs[i] * P + s[i]) % mod;
}
int max = -1;
int pos = 0;
auto gethash = [&](std::vector<i64>& h, int l, int r) -> i64 {
return ((h[r] - h[l - 1] * p[r - l + 1]) % mod + mod) % mod;
};
auto check = [&](int id, int x) -> bool {
u64 S;
if (x <= id) {
S = gethash(rhs, n - id + 1, n - id + x);
}
else {
S = (gethash(rhs, n - id + 1, n) * p[x - id] % mod + gethash(hs, id + 1, x)) % mod;
}
u64 T = ht[x];
// std::cerr << S << " " << T << '\n';
return S == T;
};
for (int i = 1; i <= n; i ++) {
int l = 0, r = n;
while (l < r) {
int mid = l + r + 1 >> 1;
// std::cerr << l << " " << r << " " << mid << '\n';
if (check(i, mid)) {
l = mid;
}
else {
r = mid - 1;
}
}
// std::cerr << l << "\n\n";
if (max < l) {
max = l;
pos = i;
}
}
std::cout << max << ' ' << pos << '\n';
}