AtCoder初学者竞赛418
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 }
双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 }
手动二分查找可以改成
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 }
对于一个子序列,如果其具有偶数个(包括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 }
用一个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 }
浙公网安备 33010602011771号