Educational Codeforces Round 95 (Rated for Div. 2)
Problem A
题意:开局:1A 两种操作: 1A->xA,yA->1B,问最少多少次操作能获得kA和kB
思路:1A->xA这个操作增加了x-1 A
要获得kB,那肯定需要y* kA + k个操作
所以总共需要(y+1) * k个A,这些需要 ceiling(((y + 1) * k - 1) / (x - 1))个操作
总共 ceiling(((y + 1) * k - 1) / (x - 1)) + k个操作
#include <iostream> using namespace std; int main(){ int t; long long x, y, z; cin >> t; while(t--){ cin>>x>>y>>z; long long swap = z; auto x1 = x-1; swap += (z + (z * y) + x1-2)/x1; cout<<swap<<endl;} return 0;}
Problem B
题意:使前缀和为负的最大序号尽可能小
思路:很简单,能排序的位置按照值大优先排序
#include <iostream> #include <algorithm> using namespace std; int a[100]; bool lk[100]; int b[100]; int main() { int t, n; cin >> t; while (t--) { cin >> n; int m = 0; for (int i = 0; i < n; i++) { cin >> a[i]; } for (int i = 0; i < n; i++) { cin >> lk[i]; if (!lk[i]) b[m++] = a[i]; } sort(b, b + m); for (int i = 0; i < n; i++) { if (!lk[i]) a[i] = b[--m]; cout << a[i] << ((i == n - 1) ? '\n' : ' '); } } return 0; }
Problem C
题意:A,B一起取n个子,都只能取1或2个,A取到1会罚1分,B取1不会罚分,0二人都不罚分,现在A,B合作,A先开始,要使罚分最低。
思路:只有三种选择:一起走2步,第一步A;一起走3步,第一步A;一起走4步,前2步A;
错误原因:数组开的太小,也是WA不是LE
#include <iostream> #include <algorithm> #include <string.h> using namespace std; int lk[200000]; int dp[200005]; int main() { int t, n; cin >> t; while (t--) { cin >> n; int m = 0; memset(lk, 0, sizeof(lk)); for (int i = 0; i < n; i++) { cin >> lk[i]; } memset(dp, 0x7f, sizeof(dp)); dp[0] = 0; for (int i = 0; i < n; i++) { for (int sum = 2; sum <= 4; sum++) { int skippt = lk[i]; if (sum > 3 && i < n - 1)skippt += lk[i + 1]; dp[i + sum] = min(dp[i + sum], dp[i] + skippt); } } for (int i = 1; i < 4; i++)dp[n] = min(dp[n], dp[n + i]); cout << dp[n] << endl; } return 0; }
Problem D
题意:有若干堆垃圾,可以选择往左扫或者右一步,要求把所有垃圾合并成最多两堆
思路:
一开始以为和连通图有关,后来发现就只是总长减去最大的线段间隔,也就是相当于将第一堆到线段左边那堆扫到一起,将线段右边那堆一直到最后一堆扫到一起,变成两个子过程,每个子过程相当于相对于中点由外向内合并所有,将所有堆都扫到中点。所以,只需要维护最大的线段这一个属性。
#include <vector> #include <string> #include <queue> #include <iostream> #include <set> #include <queue> #include <algorithm> using namespace std; int p[100000]; int main() { freopen("input.txt", "r", stdin); int n, q; set<int> st; priority_queue<pair<int, int> > prs; cin >> n >> q; for (int i = 0; i < n; i++) { cin >> p[i]; } sort(p, p + n); for (int i = 0; i < n; i++) { st.insert(p[i]); if (i > 0)prs.push(make_pair(p[i] - p[i - 1], p[i])); } if (n <= 2) { cout << 0 << endl; } else { int start_x = *st.begin(); int end_x = *prev(st.end(), 1); int big_gap = 0; while (!prs.empty()) { int gap_end_x = prs.top().second; int gap = prs.top().first; auto tmpit = st.find(gap_end_x); if (tmpit == st.end() || tmpit == st.begin() || *prev(tmpit, 1) != gap_end_x - gap) { prs.pop(); continue; } big_gap = gap; break; } cout << end_x - start_x - big_gap << endl; } for (int ci = 0; ci < q; ci++) { int op, x; cin >> op >> x; if (op == 1) { st.insert(x); } auto it = st.find(x); auto it_prev = (it == st.begin()) ? it : prev(it, 1); auto it_next = next(it, 1); if (op == 0) { if (it != st.begin() && it_next != st.end()) { prs.push(make_pair((*it_next - *it_prev), *it_next)); } st.erase(x); } else { if (it != st.begin()) { prs.push(make_pair((x - *it_prev), x)); } if (it_next != st.end()) { prs.push(make_pair((*it_next - x), *it_next)); } } if (st.size() <= 2) { cout << 0 << endl; } else { int start_x = *st.begin(); int end_x = *prev(st.end(), 1); int big_gap = 0; while (!prs.empty()) { int gap_end_x = prs.top().second; int gap = prs.top().first; auto tmpit = st.find(gap_end_x); if (tmpit == st.end() || tmpit == st.begin() || *prev(tmpit, 1) != gap_end_x - gap) { prs.pop(); continue; } big_gap = gap; break; } cout << end_x - start_x - big_gap << endl; } } return 0; }