SMU Spring 2023 Contest Round 5(2023 (ICPC) Jiangxi Provincial Contest -- Official Contest)
Problem A. Drill Wood to Make Fire
S * V >= n即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define int long long #define endl '\n' using namespace std; const int N = 2010,mod = 1e9 + 7; int n,s,v; void solve() { cin >> n >> s >> v; if(s * v >= n) cout << 1 << endl; else cout << 0 << endl; } int32_t main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int h_h = 1; cin >> h_h; while(h_h--)solve(); return 0; }
Problem B. Wonderful Array
发现 = 的个数就是看有多少 ai mod m = 0,< 的个数不好求,那么就考 虑求 > 的个数。 先将所有 ai 对 m 取模,不会影响答案。因为 0 ⩽ bi+1 − bi < m
bi mod m > bi+1 mod m ⇐⇒ ⌊bi/m⌋ < ⌊bi+1/m⌋
整体考虑的话就会发现,> 的个数就是 ⌊ bn / m ⌋
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define endl '\n' #define int long long #define inf 0x3f3f3f3f using namespace std; const int N = 2e3 + 10; //typedef long long ll; typedef pair<int,int> PII; //queue<PII> q1; map<int, int > mp; int n,m,t,k; priority_queue <int,vector<int>,greater<int> > Q; void solve() { cin >> k; vector<int> a(k); for(int i = 0;i < k;i++) cin >> a[i]; int x; cin >> n >> m >> x; for(int i = 0;i < k;i++) a[i] %= m; int sum = x % m; int num = 0; for(int i = 0;i < k;i++) num += a[i]; sum += n / k * num; for(int i = 0;i < n % k;i++) sum += a[i]; cout << n - sum / m << endl; } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr); int Ke_scholar = 1; //cin >> Ke_scholar; while(Ke_scholar--) solve(); return 0; } /* */
Problem I. Tree
我们对每个点直接维护答案,发现对于操作 1,路径上两个端点之外的点 答案不变。因此操作 1 直接对两个端点异或上这个数,操作 2 直接输出 即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define endl '\n' #define int long long using namespace std; const int N = 1e6+10, mod = 1e9 + 7; //typedef long long ll; typedef pair<int,int> PII; int n,m,t,k; map<int,int> mp; priority_queue<int> QQ; deque<int> Q; void solve() { cin >> n >> m; vector<PII> a[n + 1]; vector<int> sum(n + 1,0); for(int i = 1;i < n;i++){ int x,y,z; cin >> x >> y >> z; a[x].push_back({y,z}); a[y].push_back({x,z}); } for(int i = 1;i <= n;i++){ for(auto j : a[i]) sum[i] ^= j.second; } while(m--){ int op; cin >> op; if(op == 1){ int x,y,z; cin >> x >> y >> z; sum[x] ^= z; sum[y] ^= z; } else{ int x; cin >> x; cout << sum[x] << endl; } } } signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int Ke_scholar = 1; //cin >> Ke_scholar; while(Ke_scholar--) solve(); return 0; } /* */
Problem J. Function
给出一个正整数 n(1 ⩽ n ⩽ 105 ) 和 n 个二次项系数为 1 的二次函数,第 i 个函数形如 y = (x − i) 2 + bi(1 ⩽ bi ⩽ n)
然后给出一个正整数 m(1 ⩽ m ⩽ 105 ),表示操作总数。
操作共有两种,第一种是添加一个二次项系数为 1 的二次函数,形如 y = (x − a) 2 + b(1 ⩽ a, b ⩽ n)。第二种是询问所有二次函数在 x = a(1 ⩽ a ⩽ n) 处的最小函数值
。 具体的,每次操作会先给出操作的类型,如果是 0 表示是第一种操作,如 果是 1 表示是第二种操作。对于第一种操作,会再给出两个正整数 a, b。 对于第二种操作,则会再给出一个正整数 a。
查询 x = a 时函数的最小值,容易发现可能为最小值的函数只可能在左右 根号的范围内。 那么只要在左右根号的范围内枚举所有函数,找出最优的即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define inf 0x3f3f3f3f #define endl '\n' #define int long long #define LB long double using namespace std; const int N = 1000000000, mod = 1e9 +7; //typedef long long ll; typedef pair<int,int> PII; //queue<PII> q1; map<char, int > mp; //priority_queue <LB,vector<LB>,less<LB> > Q; int n,m,t,k; /* */ string s; void solve() { cin >> n; vector<int> b(n + 1); for(int i = 1;i <= n;i++) cin >> b[i]; int sn = sqrt(n); int q; cin >> q; while(q--){ int op; cin >> op; if(op){ int x; cin >> x; int res = LONG_LONG_MAX; for(int i = x - sn; i <= sn + x + 1;i ++){ if(i >= 0 && i < n && b[i]) res = min(res, (i - x) * ( i - x) + b[i]); } cout << res << endl; } else{ int x,y; cin >> x >> y; if(b[x]) b[x] = min(y, b[x]); else b[x] = y; } } } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr); int Ke_scholar = 1; // cin >> Ke_scholar ; while(Ke_scholar--) solve(); return 0; }
Problem K. Split
实际上就是先对n个数的差进行预处理,排序后求一个前缀和,操作0时对于这个差值是不会产生任何改变的,操作1时给一个整数k,则n - k - 1的前缀和.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr),cout.tie(nullptr); int n; cin >> n; vector<int> a(n); for(int i = 0;i < n;i ++) cin >> a[i]; int q; vector<int> ve; for(int i = 1;i < n;i ++){ int x = abs(a[i] - a[i - 1]); ve.push_back(x); } sort(ve.begin(),ve.end()); map<int,int> mp; for(int i = 0;i < ve.size();i++){ if(i == 0) mp[i] = ve[i]; else mp[i] = ve[i] + mp[i - 1]; } cin >> q; while(q--){ int op; cin >> op; if(!op){ int x; cin >> x; a[x - 1] = a[x] + a[x - 2] - a[x - 1]; } else{ int k; cin >> k; cout << mp[n - k - 1] << endl; } } return 0; } /* */
Problem L. Zhang Fei Threading Needles - Thick with Fine
输出n - 1即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define inf 0x3f3f3f3f #define endl '\n' #define int long long using namespace std; const int N = 1e9 + 10, mod = 1e9 +7; //typedef long long ll; typedef pair<int,int> PII; //queue<PII> q1; map<char, int > mp; //priority_queue <int,vector<int>,greater<int> > q2; int n,m,t,k; /* */ string s; vector<PII> a,ans; void solve() { cin >> n; cout << n - 1 << endl; } signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int Ke_scholar = 1; //cin >> Ke_scholar ; while(Ke_scholar--) solve(); return 0; }