求和
因式分解加前缀和;
#include<bits/stdc++.h> #define ll long long using namespace std; const int M = 200010; int a[M], n; ll pre[M], ans; int main(){ memset(pre, 0, sizeof(pre)); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); ll ans = 0; int i; cin >> n; for(i = 1;i <= n;i++){ cin >> a[i]; pre[i] = pre[i - 1] + a[i]; } for(i = 1;i <= n - 1;i++){ ans += a[i] * (pre[n] - pre[i]); } cout << ans; return 0; }
导弹拦截
最长不上升子序列和最长不上升子序列的最少数量,最少数量用 set 维护;
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; int a[500001], dp[500001], l[500001]; set<int> sy; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); mem(dp, 0); mem(a, 0); mem(l, 0); int n = 0, ans1 = 1, x; while(cin>>x) a[++n]=x; dp[1] = 1; l[1] = a[1]; for(int i = 2; i <= n; i++){ dp[i] = 1; if(a[i] <= l[ans1]){ dp[i] = ++ans1; }else{ int j = upper_bound(l + 1, l + ans1 + 1, a[i], greater<int>()) - l; dp[i] = j; } l[dp[i]] = a[i]; auto it = sy.lower_bound(a[i]); if(it == sy.end()){ sy.insert(a[i]); }else{ sy.erase(it); sy.insert(a[i]); } } cout << ans1 << endl << sy.size(); return 0; }
upper_bound 返回的是第一个大于给定值的元素的位置。
lower_bound 返回的是第一个不小于给定值的元素的位置。
传球游戏
模拟链,状态为第 i 次传球传给 j 的方案数;
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; int dp[31][31]; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); mem(dp, 0); int n, m; cin >> n >> m; dp[1][n] = 1; dp[1][2] = 1; for(int i = 2; i <= m; i++){ for(int j = 1; j <= n; j++){ if(j == 1){ dp[i][j] = dp[i - 1][j + 1] + dp[i - 1][n]; }else if(j == n){ dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][1]; }else{ dp[i][j] = dp[i - 1][j + 1] + dp[i - 1][j - 1]; } } } cout << dp[m][1] << endl; return 0; }
借教室
差分数组维护前 x 人每天需要的总教室数,然后依次判断有没有哪天超过可借数量,判断是否可行;然后二分答案找到第一个不满足订单;
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; ll a[1000011], diff[1000011]; int d[1000011], s[1000011], t[1000011]; int n, m; int search(int x){ mem(diff, 0); for(int i = 1; i <= x; i++){ diff[s[i]] += d[i]; diff[t[i] + 1] -= d[i]; } ll tag = 0; for(int i = 1; i <= n; i++){ tag += diff[i]; if(tag > a[i]){ return -1; } } return 0; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; for(int i = 1; i <= n; i++){ cin >> a[i]; } for(int i = 1; i <= m; i++){ cin >> d[i] >> s[i] >> t[i]; } int ans = search(m); cout << ans << endl; if(ans != 0){ int l = 1, r = m, mid = 0; while(l < r){ mid = (l + r) >> 1; if(search(mid) == 0){ l = mid + 1; }else{ r = mid; } } cout << l; } return 0; }
守望者的逃离
贪心,有魔法就魔法,没魔法看等 CD 和跑步哪个赚,最后看能跑多远;
#include<bits/stdc++.h> #define ll long long #define endl "\n" #define mem(vis, num) memset(vis, num, sizeof(vis)); using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int m, s, t, l = 0, r, p; cin >> m >> s >> t; r = s; int w = 0; for(int i = 1;i <= t; i++){ if(m >= 10){ m -= 10; l += 60; }else{ p = 10 - m; r = (p % 4) == 0 ? (p / 4) + 1 : (p / 4) + 2; if(t - i + 1 >= r && s - l > 17 * r){ m += 4; }else{ l += 17; } } if(l >= s){ cout << "Yes" << endl << i; break; } } if(l < s){ cout << "No" << endl << l; } return 0; }