SRM 410(1-250pt, 1-500pt)
DIV1 250pt
题意:对于图G,有一些点和边,点中有一些点称为特殊点。问在所有特殊点最终不能处于同一个联通块的条件下,最多能给在图G中添加多少条边。
解法:首先,对于图G,处理出它有哪些联通块,然后,不含有特殊点的联通块要连接到某一个含有特殊点的联通块上。连接哪一个能使添加的边最多呢?当然是连接含有点数最多的含特殊点的联通块。
tag:graph, greedy
1 // BEGIN CUT HERE 2 /* 3 * Author: plum rain 4 * score : 5 */ 6 /* 7 8 */ 9 // END CUT HERE 10 #line 11 "AddElectricalWires.cpp" 11 #include <sstream> 12 #include <stdexcept> 13 #include <functional> 14 #include <iomanip> 15 #include <numeric> 16 #include <fstream> 17 #include <cctype> 18 #include <iostream> 19 #include <cstdio> 20 #include <vector> 21 #include <cstring> 22 #include <cmath> 23 #include <algorithm> 24 #include <cstdlib> 25 #include <set> 26 #include <queue> 27 #include <bitset> 28 #include <list> 29 #include <string> 30 #include <utility> 31 #include <map> 32 #include <ctime> 33 #include <stack> 34 35 using namespace std; 36 37 #define clr0(x) memset(x, 0, sizeof(x)) 38 #define clr1(x) memset(x, -1, sizeof(x)) 39 #define pb push_back 40 #define sz(v) ((int)(v).size()) 41 #define all(t) t.begin(),t.end() 42 #define zero(x) (((x)>0?(x):-(x))<eps) 43 #define out(x) cout<<#x<<":"<<(x)<<endl 44 #define tst(a) cout<<a<<" " 45 #define tst1(a) cout<<#a<<endl 46 #define CINBEQUICKER std::ios::sync_with_stdio(false) 47 48 typedef vector<int> vi; 49 typedef vector<string> vs; 50 typedef vector<double> vd; 51 typedef pair<int, int> pii; 52 typedef long long int64; 53 54 const double eps = 1e-8; 55 const double PI = atan(1.0)*4; 56 const int inf = 2139062143 / 2; 57 58 class AddElectricalWires 59 { 60 public: 61 int f[100]; 62 bool v[100]; 63 64 int find(int x) 65 { 66 if (x != f[x]) f[x] = find(f[x]); 67 return f[x]; 68 } 69 70 int maxNewWires(vector <string> p, vector <int> num){ 71 clr0 (v); 72 for (int i = 0; i < sz(num); ++ i) v[num[i]] = 1; 73 for (int i = 0; i < sz(p); ++ i) f[i] = i; 74 for (int i = 0; i < sz(p); ++ i) 75 for (int j = 0; j < sz(p); ++ j) if (p[i][j] == '1'){ 76 int t1 = find(i), t2 = find(j); 77 if ((v[t1] && v[t2]) || (t1 == t2)) continue; 78 if (!v[t1]) f[t1] = t2; 79 else f[t2] = t1; 80 81 } 82 int ans = 1, idx = num[0]; 83 for (int i = 0; i < sz(num); ++ i){ 84 int tmp = 0; 85 for (int j = 0; j < sz(p); ++ j) 86 if (find(j) == num[i]) ++ tmp; 87 if (tmp > ans) 88 idx = num[i], ans = tmp; 89 } 90 int ret = 0; 91 for (int i = 0; i < sz(p); ++ i) 92 for (int j = i+1; j < sz(p); ++ j) if (p[i][j] == '0'){ 93 int t1 = find(i), t2 = find(j); 94 if (t1 == t2){ 95 ++ ret; continue; 96 } 97 if (v[t1] && v[t2]) continue; 98 if (!v[t1] && !v[t2]){ 99 ++ ret; f[t1] = t2; continue; 100 } 101 if (t1 == idx || t2 == idx){ 102 ++ ret; 103 if (t1 == idx) f[t2] = idx; 104 else f[t1] = idx; 105 } 106 } 107 return ret; 108 } 109 110 // BEGIN CUT HERE 111 public: 112 void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); } 113 private: 114 template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); } 115 void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } } 116 void test_case_0() { string Arr0[] = {"000","000","000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; verify_case(0, Arg2, maxNewWires(Arg0, Arg1)); } 117 void test_case_1() { string Arr0[] = {"000","000","000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0,1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 1; verify_case(1, Arg2, maxNewWires(Arg0, Arg1)); } 118 void test_case_2() { string Arr0[] = {"01","10"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 0; verify_case(2, Arg2, maxNewWires(Arg0, Arg1)); } 119 void test_case_3() { string Arr0[] = {"00000","00000","00000","00000","00000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0,1,2,3,4}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 0; verify_case(3, Arg2, maxNewWires(Arg0, Arg1)); } 120 void test_case_4() { string Arr0[] = {"01000","10100","01010","00100","00000"}; vector <string> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {2,4}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 3; verify_case(4, Arg2, maxNewWires(Arg0, Arg1)); } 121 122 // END CUT HERE 123 124 }; 125 126 // BEGIN CUT HERE 127 int main() 128 { 129 // freopen( "a.out" , "w" , stdout ); 130 AddElectricalWires ___test; 131 ___test.run_test(-1); 132 return 0; 133 } 134 // END CUT HERE
DIV1 500pt
题意:给定整数k,n和一个数组A[],要按顺序访问范围为0-(n-1)的数轴上编号为A[i]的点,访问的方法如下。首先,找到一段长度为k的连续的点,(比如编号为x, x+1, x+2...x+k-1),然后查看缓存中的点,有三种可能:某点在缓存中但这次不需要访问,则移出缓存;某点不在缓存中但这次要访问,访问该点并将它加入缓存;某点在缓存中且要访问,不访问该点但将其留在缓存中。要按顺序访问A[i]中的点,最少需要进行多少次访问操作。
n <= 10^9, k <= n, A.size() <= 50。
注意,如果A[] = {2, 3, 10},k = 3,n = 1000则只需访问2, 3, 4, 8, 9, 10即可。
解法:本题的关键点在于要注意到一点,要访问A[i],最优解访问的连续k个点只有两类可能:A[j], A[j]+1...A[j]+k-1和A[j]-k+1, A[j]-k+2...A[j]。(*)
所以,先预处理出可能从哪些点开始访问。然后,由于要按顺序访问A[i],所以只需要做一遍dp即可。
tag:dp, think
1 // BEGIN CUT HERE 2 /* 3 * Author: plum rain 4 * score : 5 */ 6 /* 7 8 */ 9 // END CUT HERE 10 #line 11 "ContiguousCache.cpp" 11 #include <sstream> 12 #include <stdexcept> 13 #include <functional> 14 #include <iomanip> 15 #include <numeric> 16 #include <fstream> 17 #include <cctype> 18 #include <iostream> 19 #include <cstdio> 20 #include <vector> 21 #include <cstring> 22 #include <cmath> 23 #include <algorithm> 24 #include <cstdlib> 25 #include <set> 26 #include <queue> 27 #include <bitset> 28 #include <list> 29 #include <string> 30 #include <utility> 31 #include <map> 32 #include <ctime> 33 #include <stack> 34 35 using namespace std; 36 37 #define clr0(x) memset(x, 0, sizeof(x)) 38 #define clr1(x) memset(x, -1, sizeof(x)) 39 #define pb push_back 40 #define sz(v) ((int)(v).size()) 41 #define all(t) t.begin(),t.end() 42 #define zero(x) (((x)>0?(x):-(x))<eps) 43 #define out(x) cout<<#x<<":"<<(x)<<endl 44 #define tst(a) cout<<a<<" " 45 #define tst1(a) cout<<#a<<endl 46 #define CINBEQUICKER std::ios::sync_with_stdio(false) 47 48 typedef vector<int> vi; 49 typedef vector<string> vs; 50 typedef vector<double> vd; 51 typedef pair<int, int> pii; 52 typedef long long int64; 53 54 const double eps = 1e-8; 55 const double PI = atan(1.0)*4; 56 const int inf = 2139062143 / 2; 57 const int64 llinf = 1LL<<62; 58 59 class ContiguousCache 60 { 61 public: 62 int64 d[100][200]; 63 64 int64 over(int a, int b, int c, int d, int k) 65 { 66 if (d < a || c > b) return k; 67 return max(b, d) - min(a, c) + 1 - k; 68 } 69 70 long long minimumReads(int len, int k, vector <int> pos){ 71 vi x; 72 for (int i = 0; i < sz(pos); ++ i){ 73 x.pb (min(pos[i], len-k)); 74 x.pb (max(0, pos[i]-k+1)); 75 } 76 x.erase(unique(x.begin(), x.end()), x.end()); 77 78 for (int i = 0; i < sz(pos); ++ i) 79 for (int j = 0; j < sz(x); ++ j) d[i][j] = llinf; 80 81 for (int i = 0; i < sz(x); ++ i) if (x[i] <= pos[0] && x[i]+k-1 >= pos[0]) 82 d[0][i] = k; 83 84 for (int i = 1; i < sz(pos); ++ i) 85 for (int j = 0; j < sz(x); ++ j) if (x[j] <= pos[i] && x[j]+k-1 >= pos[i]) 86 for (int t = 0; t < sz(x); ++ t) if (d[i-1][t] != llinf) 87 d[i][j] = min(d[i][j], d[i-1][t] + over(x[t], x[t]+k-1, x[j], x[j]+k-1, k)); 88 89 int64 ret = llinf; 90 for (int i = 0; i < sz(x); ++ i) ret = min(ret, d[sz(pos)-1][i]); 91 return ret; 92 } 93 94 // BEGIN CUT HERE 95 public: 96 void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); } 97 private: 98 template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); } 99 void verify_case(int Case, const long long &Expected, const long long &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } } 100 void test_case_0() { int Arg0 = 100; int Arg1 = 3; int Arr2[] = {0, 2, 16, 13}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 7LL; verify_case(0, Arg3, minimumReads(Arg0, Arg1, Arg2)); } 101 void test_case_1() { int Arg0 = 100; int Arg1 = 10; int Arr2[] = {1,10,19,28,30,37}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 29LL; verify_case(1, Arg3, minimumReads(Arg0, Arg1, Arg2)); } 102 void test_case_2() { int Arg0 = 1000000000; int Arg1 = 500000000; int Arr2[] = {0, 999999999, 1, 500000000, 500000001, 987654321}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 1987654320LL; verify_case(2, Arg3, minimumReads(Arg0, Arg1, Arg2)); } 103 void test_case_3() { int Arg0 = 8; int Arg1 = 2; int Arr2[] = {7}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); long long Arg3 = 2LL; verify_case(3, Arg3, minimumReads(Arg0, Arg1, Arg2)); } 104 105 // END CUT HERE 106 107 }; 108 109 // BEGIN CUT HERE 110 int main() 111 { 112 // freopen( "a.out" , "w" , stdout ); 113 ContiguousCache ___test; 114 ___test.run_test(-1); 115 return 0; 116 } 117 // END CUT HERE
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。