Good Bye 2017 F. New Year and Rainbow Roads[模拟][贪心]
题目:http://codeforces.com/contest/908/problem/F
题意:给出n个点和他所在坐标,每个点有R,G,B三种颜色中的一种,坐标严格递增。要求在删除所有R或删除所有B后的所有点必须直接或间接链接在一起,每一次链接的代价为距离差,求最小代价。
分析:考虑以G为分隔符,每次处理每一段两个相邻G点之间的所有R和B(两个G中间有R且有B的情况),如果想让删除R或B后依然链接,有两种最优化策略。
*第一种,两个G点通过中间的R和B相连,长度为(posG[i+1]-posG[i])*2,这样在删除哪一种点以后另一种点都可以链接两端的G。
*第二种,两个G点互相连接,并从两个G点向外延伸线段连接R和B,长度为(posG[i+1]-posG[i])*3-ansR-ansB ansR代表相邻的R和G点的最长间隔,因为有两个G相连,所以在B的线段上删除一条间隔时不会断开链接,例如GBRG,如果B离第一个G更远则删除他和第一个G的链接,所以找最长的间隔删除,ansB同理。可以在线性时间内处理每一对相邻G点。
*其他中间没有B或R的情况类似处理。
*边缘的B直接串成一串链接到最近的G为最优答案,R同理。
*对于没有G的特殊情况,直接链接所有的R和所有的B即可。
代码:
1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,102400000") 3 #pragma GCC optimize("Ofast") 4 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") 5 #include<iostream> 6 #include<cstdio> 7 #include<fstream> 8 #include<iomanip> 9 #include<algorithm> 10 #include<cmath> 11 #include<deque> 12 #include<vector> 13 #include<bitset> 14 #include<queue> 15 #include<string> 16 #include<cstring> 17 #include<map> 18 #include<stack> 19 #include<set> 20 #include<functional> 21 #define pii pair<ll,ll> 22 #define mod 1000000007 23 #define mp make_pair 24 #define pi acos(-1) 25 #define eps 0.00000001 26 #define mst(a,i) memset(a,i,sizeof(a)) 27 #define all(n) n.begin(),n.end() 28 #define lson(x) ((x<<1)) 29 #define rson(x) ((x<<1)|1) 30 #define inf 0x3f3f3f3f 31 typedef long long ll; 32 typedef unsigned long long ull; 33 using namespace std; 34 const ll maxn = 3e5 + 5; 35 pii a[maxn]; 36 vector<ll>r, g, b; 37 int main() 38 { 39 ios::sync_with_stdio(false); 40 cin.tie(0); cout.tie(0); 41 ll i, j, k, m, n; 42 cin >> n; 43 char ch; 44 ll mode = 0; 45 for (ll i = 1; i <= n; ++i) 46 { 47 cin >> a[i].first >> ch; 48 if (ch == 'R') { a[i].second = 1; r.push_back(a[i].first); } 49 else if (ch == 'B') { a[i].second = 2; b.push_back(a[i].first); } 50 else { a[i].second = 3; g.push_back(a[i].first); } 51 if (ch == 'G')mode = 1; 52 } 53 ll ans = 0; 54 55 if (mode == 0) 56 { 57 ll pre = -1; 58 for (ll i = 1; i <= n; ++i) 59 { 60 if (a[i].second != 1)continue; 61 if (pre != -1)ans += a[i].first - pre; 62 pre = a[i].first; 63 } 64 pre = -1; 65 for (ll i = 1; i <= n; ++i) 66 { 67 if (a[i].second != 2)continue; 68 if (pre != -1)ans += a[i].first - pre; 69 pre = a[i].first; 70 } 71 } 72 else 73 { 74 for (ll i = 0; i < g.size(); ++i) 75 { 76 if (i == 0) 77 { 78 ll cas = lower_bound(b.begin(), b.end(), g[i]) - b.begin(); 79 if (cas != 0)ans += g[i] - b[0]; 80 cas = lower_bound(r.begin(), r.end(), g[i]) - r.begin(); 81 if (cas != 0)ans += g[i] - r[0]; 82 } 83 if (i == g.size() - 1) 84 { 85 ll cas = lower_bound(b.begin(), b.end(), g[i]) - b.begin(); 86 if (cas != b.size())ans += b[b.size() - 1] - g[i]; 87 cas = lower_bound(r.begin(), r.end(), g[i]) - r.begin(); 88 if (cas != r.size())ans += r[r.size() - 1] - g[i]; 89 } 90 if (i != g.size() - 1) 91 { 92 ll maxa = inf, maxb = inf; 93 ll st = lower_bound(b.begin(), b.end(), g[i]) - b.begin(); 94 ll ed = lower_bound(b.begin(), b.end(), g[i + 1]) - b.begin() - 1; 95 if (st < b.size() && b[st] < g[i + 1]) 96 { 97 ll temp = b[st] - g[i]; 98 temp = max(temp, g[i + 1] - b[ed]); 99 for (ll j = st + 1; j <= ed; ++j) 100 temp = max(temp, b[j] - b[j - 1]); 101 maxa = temp; 102 } 103 st = lower_bound(r.begin(), r.end(), g[i]) - r.begin(); 104 ed = lower_bound(r.begin(), r.end(), g[i + 1]) - r.begin() - 1; 105 if (st<r.size()&&r[st] < g[i + 1]) 106 { 107 ll temp = r[st] - g[i]; 108 temp = max(temp, g[i + 1] - r[ed]); 109 for (ll j = st + 1; j <= ed; ++j) 110 temp = max(temp, r[j] - r[j - 1]); 111 maxb = temp; 112 } 113 ll sum = g[i + 1] - g[i]; 114 if (maxa == inf&&maxb == inf)ans += sum; 115 else if (maxa == inf)ans += sum + sum - maxb; 116 else if (maxb == inf)ans += sum + sum - maxa; 117 else 118 ans += min(sum * 2LL, sum * 3LL - maxa - maxb); 119 } 120 } 121 } 122 cout << ans << endl; 123 return 0; 124 }