C. Glass Carving 正着做或者倒着做都可以
Posted stupid_one
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C. Glass Carving 正着做或者倒着做都可以相关的知识,希望对你有一定的参考价值。
http://codeforces.com/problemset/problem/527/C
这题总体思路就是,每画一条线,然后就找到x间距的最max值和y间距的最max值,相乘就是当前的ans
那么我需要维护这样的一个数列,每次往里面添加一个元素,然后查询相邻两个元素的差值的最大值。
倒着做比较简单,首先把所有元素插上去,然后最大值直接暴力算一次。然后后来只有删除操作,这个操作只会让最大值变大。
每次删除后,检查上面和下面的新间距,和最大值比较一下就好。
#include <bits/stdc++.h> #define ios ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; set<int> ss[2]; LL ans[200000 + 20]; struct Node { char op; int val; }node[200000 + 20]; void fuck(int id) { if (node[id].op == \'H\') { ss[1].erase(node[id].val); } else ss[0].erase(node[id].val); } void work() { int w, h, n; cin >> w >> h >> n; ss[0].insert(0); ss[0].insert(w); ss[1].insert(0); ss[1].insert(h); set<int> :: iterator it1, it2; for (int i = 1; i <= n; ++i) { char str[2]; int val, flag = false; scanf("%s%d", str, &val); if (str[0] == \'H\') { ss[1].insert(val); } else ss[0].insert(val); node[i].op = str[0]; node[i].val = val; } int mx1 = 1; // v it2 = ss[0].begin(); it2++; for (it1 = ss[0].begin(); it2 != ss[0].end(); ++it2, ++it1) { mx1 = max(mx1, *it2 - *it1); } int mx2 = -inf; it2 = ss[1].begin(); it2++; for (it1 = ss[1].begin(); it2 != ss[1].end(); ++it2, ++it1) { mx2 = max(mx2, *it2 - *it1); } ans[n] = 1LL * mx1 * mx2; // cout << mx1 << " " << mx2 << endl; fuck(n); mx1 = 1; // v it2 = ss[0].begin(); it2++; for (it1 = ss[0].begin(); it2 != ss[0].end(); ++it2, ++it1) { mx1 = max(mx1, *it2 - *it1); } mx2 = 1; it2 = ss[1].begin(); it2++; for (it1 = ss[1].begin(); it2 != ss[1].end(); ++it2, ++it1) { mx2 = max(mx2, *it2 - *it1); } for (int i = n - 1; i >= 1; --i) { if (node[i].op == \'H\') { it1 = ss[1].lower_bound(node[i].val); it2 = it1; it2++; mx2 = max(mx2, *it2 - *it1); it2 = it1; it1--; mx2 = max(mx2, *it2 - *it1); it1++; } else { it1 = ss[0].lower_bound(node[i].val); it2 = it1; it2++; mx1 = max(mx1, *it2 - *it1); it2 = it1; it1--; mx1 = max(mx1, *it2 - *it1); it1++; } it2 = it1; it2++; it1--; fuck(i); ans[i] = 1LL * mx1 * mx2; if (node[i].op == \'H\') { mx2 = max(mx2, *it2 - *it1); } else mx1 = max(mx1, *it2 - *it1); } for (int i = 1; i <= n; ++i) { cout << ans[i] << endl; } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }
写的很乱,因为是绝杀的。
正着也可以。
用一个multiset来维护当前拥有的差值,一开始是h
然后每添加一条边,可以找出在原数组中的上界和下界,这个差值是要删除的那个差值,然后添加新差值即可。
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; set<int> x, y; multiset<int> xx, yy; void work() { int w, h, n; cin >> w >> h >> n; x.insert(0), x.insert(w); y.insert(0), y.insert(h); xx.insert(w), yy.insert(h); for (int i = 1; i <= n; ++i) { char str[2]; int pos; cin >> str >> pos; if (str[0] == \'H\') { auto it1 = y.lower_bound(pos); int d1 = *it1; it1--; int d2 = *it1; auto del = yy.lower_bound(d1 - d2); yy.erase(del); yy.insert(d1 - pos); yy.insert(pos - d2); y.insert(pos); } else { auto it1 = x.lower_bound(pos); int d1 = *it1; it1--; int d2 = *it1; auto del = xx.lower_bound(d1 - d2); xx.erase(del); xx.insert(d1 - pos); xx.insert(pos - d2); x.insert(pos); } auto itx = xx.rbegin(), ity = yy.rbegin(); cout << 1LL * (*itx) * (*ity) << endl; } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif IOS; work(); return 0; }
以上是关于C. Glass Carving 正着做或者倒着做都可以的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 527C Glass Carving (最长连续0变形+线段树)