fyy2048

导航

AtCoder初学者竞赛418

A - I'm a teapot

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 bool solve()
 5 {
 6     int n;
 7     cin >> n;
 8     string s;
 9     cin >> s;
10     
11     if(n < 3)return false;
12     return s.substr(n - 3) == "tea";
13 }
14 
15 int main()
16 {
17     if(solve())cout << "Yes" << endl;
18     else cout << "No" << endl;
19     return 0;
20 }

B - You're a teapot

双for暴力计算每个区间最大值,注意题意要求头尾都是't'这个字符

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 void solve()
 5 {
 6     string s;
 7     cin >> s;
 8     int n = (int)s.length();
 9     double maxn = 0.0;
10     for(int i = 0;i < n;i ++)
11     {
12         for(int j = i + 1;j < n;j ++)
13         {
14             if(s[i] == 't' && s[j] == 't')
15             {
16                 int cnt = 0;
17                 for(int k = i;k <= j;k ++)
18                     if(s[k] == s[i])
19                         cnt ++;
20                 if(cnt < 3)continue;
21                 maxn = max(maxn,double(cnt - 2) / (j - i - 1));
22             }
23         }
24     }
25     printf("%.12lf",maxn);
26 }
27 
28 int main()
29 {
30     solve();
31     return 0;
32 }

C - Flush

手动二分查找可以改成

lower_bound(迭代器,迭代器,val):找到第一个大于等于val的位置

upper_bound(迭代器,迭代器,val):找到第一个大于val的位置 

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
    int n,q;
    cin >> n >> q;
    vector<ll>a(n + 1,0);
    vector<ll>S(n + 1,0);
    ll sum = 0;
    for(int i = 1;i <= n;i ++)
    {
        cin >> a[i];
        sum += a[i];
    }
    sort(a.begin() + 1,a.end());
    for(int i = 1;i <= n;i ++)
        S[i] = S[i - 1] + a[i];
    ll maxn = a[n];
//    cout <<"sum:" << sum << endl;
    while(q --)
    {
        ll b;
        cin >> b;
        if(b > maxn)cout << -1 << endl;
        else {
            int l = 1,r = n;
            int t = 0;
            while(l <= r)
            {
                int m = (l + r) / 2;
                if(a[m] >= b){
                    t = m;
                    r = m - 1;
                }else l = m + 1;
            }
//            cout << t << endl;
//            cout << S[t - 1] << " " << (n - t + 1) << " " << (b - 1) << endl;
            cout << S[t - 1] + (n - t + 1) * (b - 1) + 1 << endl;
        }
    }
    
}

int main()
{
    solve();
    return 0;
}

 赛后优化:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 using ll = long long;
 4 void solve()
 5 {
 6     int n,q;
 7     cin >> n >> q;
 8     vector<ll>a(n + 1,0);
 9     vector<ll>S(n + 1,0);
10     for(int i = 1;i <= n;i ++)
11         cin >> a[i];
12     sort(a.begin() + 1,a.end());
13     for(int i = 1;i <= n;i ++)
14         S[i] = S[i - 1] + a[i];
15     while(q --)
16     {
17         ll b;
18         cin >> b;
19         if(b > a[n])cout << -1 << endl;
20         else {
21             int t = distance(a.begin(),lower_bound(a.begin(),a.end(),b));
22             t --;
23             cout << S[t] + (n - t) * (b - 1) + 1 << endl;
24         }
25     }
26 }
27 
28 int main()
29 {
30     solve();
31     return 0;
32 }

D - XNOR Operation

对于一个子序列,如果其具有偶数个(包括0)个0,则其同或结果必定可以为1

问题转化为区间内有偶数个0的个数,记录pre为前i个数0的个数,odd_cnt,even_cnt分别记录全局的pre为奇数的个数和偶数的个数,即l,r区间要满足题意,则pre_r和pre_(l - 1)的奇偶性质应该一样,又因为所有满足pre为偶数的除了和别的位置配对,也可以到该位置的所有字符视为一个区间(也可以认为是最前面有个pre为偶数(0)的空字符位置):如1100,下标1-4,如果只配对,只有:1(1,2位置配对),100(1,4位置配对),00(2,4位置配对),显然缺少:1(0位置和1位置),11(0位置和2位置),1100(0位置和4位置)

使用pre ^= 1快速更改奇偶性,pre初始为0

处理偶数,可以初始化偶数计数器为1,或者改n(n - 1)/2为(n + 1)n / 2

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 int main() {
 4     ios::sync_with_stdio(false);
 5     cin.tie(nullptr);
 6     int n;
 7     string T;
 8     cin >> n >> T;
 9     long long a[2] = {0, 0};
10     a[0] = 1;
11     int pre = 0;
12     for (char ch : T) {
13         if (ch == '0') {
14             pre ^= 1;
15         }
16         a[pre]++;
17     }
18     long long ans = a[0] * (a[0] - 1) / 2 + a[1] * (a[1] - 1) / 2;
19     cout << ans << "\n";
20     return 0;
21 }

E - Trapezium

用一个unorderd_map记录斜率相同的边的个数,用另一个map记录斜率相同且边长度相同边的个数,前配对数减后配对数的一半就是梯形数(后者实际在记录平行四边形的数量,由于前面计算梯形时将平四计算了两倍,且后面专门计算平四也计算了两倍,所以要减去一半的后者)

第一个开map超时

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 using ll = long long;
 4 int n;
 5 void solve()
 6 {
 7     cin >> n;
 8     vector<pair<ll,ll>>pt(n);
 9     unordered_map<double,ll>mp;
10     map<pair<double,ll>,int>rect;
11     ll ans = 0,rects = 0;
12     for(int i = 0;i < n;i ++)
13     {
14         cin >> pt[i].first >> pt[i].second;
15         for(int j = 0;j < i;j ++)
16         {
17             auto [ix,iy] = pt[i];
18             auto [jx,jy] = pt[j];
19             double k = 0;
20             if(ix - jx == 0)k = 1000000.0;
21             else k = (iy - jy) / (double)(ix - jx);
22             
23             ans += mp[k];
24             mp[k] ++;
25             
26             //两条边平行就是梯形,两边平行且相等就是平四,且两边对于平四都计算了两次
27             ll dis = (ix - jx) * (ix - jx) + (iy - jy) * (iy - jy);
28             rects += rect[{k,dis}];
29             rect[{k,dis}] ++;
30         }
31     }
32     cout << ans - rects / 2 << endl;
33 }
34 
35 int main()
36 {
37     ios_base::sync_with_stdio(0),cin.tie(NULL),cout.tie(NULL);
38     solve();
39     return 0;
40 }

 

posted on 2025-08-11 12:38  春日轻轨  阅读(5)  评论(0)    收藏  举报