AtCoder Regular Contest 112 (3 / 6)
A、A - B = C
题目:给定L、R,求问存在多少个A、B、C三元组,使得A=B+C,其中L <= A <= R, L <= B <= R, L <= C <= R
答案:针对一个固定的A,存在满足条件的(B、C)两元组的数量为 A - 2 * L + 1,所以当你遍历A时,答案为一个等差数列,最小值=1,最大值=R - 2 * L + 1,差=1,则对等差数列求和即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 7; 5 const ll mod = 1e9 + 7; 6 7 int main() 8 { 9 int t; 10 cin >> t; 11 while(t--){ 12 int l, r; 13 cin >> l >> r; 14 ll ans = max(0, (r - 2 * l + 2)) * 1LL * max(0, (r - 2 * l + 1)) / 2; 15 cout << ans << "\n"; 16 } 17 return 0; 18 }
B、B - -- - B
题目:你有一个数字B 和 C 元钱,你可以做如下两种操作:1)花费1元对数字B乘以-1,2)花费2元对数字B减去1,问你最终有可能得到多少个数字。
答案:针对B,你可以一直减1,扩大在坐标轴上左边的范围;还可以先*-1,再不断减,扩大范围。针对你在坐标轴左右两侧的每一侧,你都可以获得一定的可达范围,那么同时你也可以*-1,获得同绝对值下的另一端的范围。最终你会发现,B两侧相距 C / 2的点都可以达到,对0点求对称,坐标轴另一侧可以达到,大概距离为 C / 2 * 2 * 2,再考虑不同情况去重即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 7; 5 const ll mod = 1e9 + 7; 6 7 int main() 8 { 9 ll b, c; 10 cin >> b >> c; 11 ll ans = 0, l, r; 12 if(b > 0){ 13 if(b - (c / 2) > 0){ 14 ans += c / 2 * 2 + 2; 15 if(c > 0 && c % 2 == 0)--ans; 16 --c; 17 ans += c / 2 * 2; 18 if(c > 0 && c % 2 == 0)--ans; 19 } 20 else{ 21 ans += b * 2 + 1; 22 --c; 23 ans += c / 2 * 2; 24 if(c > 0 && c % 2 == 0)--ans; 25 } 26 } 27 else{ 28 ans += c / 2 * 2 + 2; 29 if(c > 0 && c % 2 == 0)--ans; 30 if((c - 1) / 2 >= b * -1)ans += b * -1 * 2 - 1; 31 else{ 32 ans += (c - 1) / 2 * 2; 33 if((c - 1) % 2 == 0)--ans; 34 } 35 } 36 cout << ans << "\n"; 37 return 0; 38 }
C、DFS Game
题目:题目是个游戏,比较负责,就不翻译了。https://atcoder.jp/contests/arc112/tasks/arc112_c
答案:主要难点在于针对不同子树遍历的优先级选择上,即最先选择哪颗子树去遍历;每颗子树有两个属性是可以提前求得的:1)遍历完该子树之后选择权是否会转移,2)遍历完该子树会相会少获得几个coin;那么遍历的优先级如下
1、当损失都为负值时,即遍历该树能赚,那么优先考虑遍历完选择权不会转移的子树(因为选择权不转移,下次还可以继续优选选择),即损失为偶数的子树(损失为偶数,代表遍历完选择权不会转移,反之亦然)
2、当损失一负一正时,优先考虑负值,因为负值可以获得正加权,即能赚
3、当损失两正时,优先考虑奇数,即选择权转化,因为要下次把锅刷给对方(锅就代表遍历完子树是吃亏的)
4、当损失为正数且同奇偶性时,先考虑小值,尽量少损失一些
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 7; 5 const ll mod = 1e9 + 7; 6 7 vector<int> v[maxn]; 8 bool comp(pair<int, int> x, pair<int, int> y){ 9 int a = x.first, b = y.first; 10 if(a < 0 || b < 0){ 11 if(a < 0 && b < 0 && a % 2 != b % 2){ 12 return a % 2 == 0; 13 } 14 return a < b; 15 } 16 if(a % 2 != b % 2){ 17 return a % 2 == 1; 18 } 19 return a < b; 20 } 21 pair<int, int> dfs(int x, int pre = 0){ 22 vector<pair<int, int>> vn; 23 for(int y: v[x]){ 24 pair<int, int> now = dfs(y); 25 vn.push_back(now); 26 } 27 sort(vn.begin(), vn.end(), comp); 28 int a[2], ins = 0; 29 a[0] = 1; 30 a[1] = 0; 31 //cout << "x = " << x << '\n'; 32 for(pair<int, int> tmp: vn){ 33 int x = tmp.first, y = tmp.second; 34 //cout << ins << " " << x << " " << y << " " << y - x << " " << a[0] << " " << a[1] << "\n"; 35 a[ins] += y; 36 a[ins ^ 1] += y - x; 37 if(x % 2 != 0){ 38 ins ^= 1; 39 } 40 } 41 //cout << "x = " << x << " " << a[0] - a[1] << " " << a[0] << " " << a[1] << "\n"; 42 return make_pair(a[0] - a[1], a[0]); 43 } 44 int main() 45 { 46 int n; 47 cin >> n; 48 for(int i = 2; i <= n; ++i){ 49 int x; 50 cin >> x; 51 v[x].push_back(i); 52 } 53 pair<int, int> ans = dfs(1); 54 cout << ans.second << "\n"; 55 return 0; 56 }