By xiaruize
模拟题
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int,int> #define pis pair<int,string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i,x,y) for(int i=x;i<=y;i++) #define repp(i,x,y) for(int i=x;i>=y;i--) #define Yes cout<<"Yes" <<endl #define YES cout<<"YES" <<endl #define No cout<<"No" <<endl #define NO cout<<"NO" <<endl #define debug(x) cerr<<#x<<": " <<x<<endl #define double long double const int INF=0x3f3f3f3f ;const int MOD=1000000007 ;const int N=2e5 +10 ;signed main () { string s="atcoder" ; int l,r; cin>>l>>r; cout<<s.substr (l-1 ,r-l+1 )<<endl; return 0 ; }
很明显,所有的黑色格子距离最近的边界都是奇数
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i, x, y) for (int i = x; i <= y; i++) #define repp(i, x, y) for (int i = x; i >= y; i--) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define debug(x) cerr << #x << ": " << x << endl #define double long double const int INF = 0x3f3f3f3f ;const int MOD = 1000000007 ;const int N = 2e5 + 10 ;int r, c;bool a[16 ][16 ];signed main () { cin >> r >> c; if (min (min (r, 15 - r + 1 ), min (c, 15 - c + 1 )) & 1 ) cout << "black" << endl; else cout << "white" << endl; return 0 ; }
二进制枚举
二进制枚举 简单来说,就是通过一个数二进制下每一位的数字(0/1),表示当前为的一种是否状态
例如本题中,每一位就表示当前行、列是否被选中
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i, x, y) for (int i = x; i <= y; i++) #define repp(i, x, y) for (int i = x; i >= y; i--) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define debug(x) cerr << #x << ": " << x << endl #define double long double const int INF = 0x3f3f3f3f ;const int MOD = 1000000007 ;const int N = 2e5 + 10 ;int h, w;int hh, ww;int a[15 ][15 ];int b[15 ][15 ];signed main () { cin >> h >> w; for (int i = 1 ; i <= h; i++) for (int j = 1 ; j <= w; j++) cin >> a[i][j]; cin >> hh >> ww; for (int i = 1 ; i <= hh; i++) for (int j = 1 ; j <= ww; j++) cin >> b[i][j]; for (int mskh = 0 ; mskh < (1 << h); mskh++) { int cnt = 0 ; for (int i = 0 ; i < h; i++) if (mskh & (1 << i)) cnt++; if (cnt != h - hh) continue ; for (int mskw = 0 ; mskw < (1 << w); mskw++) { int cnt = 0 ; for (int i = 0 ; i < w; i++) if (mskw & (1 << i)) cnt++; if (cnt != w - ww) continue ; int hp = 1 , hw = 1 ; bool f = true ; for (int i = 1 ; i <= h; i++) { for (int j = 1 ; j <= w; j++) { if ((mskh & (1 << (i - 1 ))) || ((mskw & (1 << (j - 1 ))))) continue ; if (b[hp][hw] != a[i][j]) { f = false ; break ; } hw++; if (hw == ww + 1 ) hw = 1 , hp++; } if (!f) break ; } if (f) { Yes; return 0 ; } } } No; return 0 ; }
很典型的逆序对题,n 2 n^2 n 2 求逆序对
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i, x, y) for (int i = x; i <= y; i++) #define repp(i, x, y) for (int i = x; i >= y; i--) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define debug(x) cerr << #x << ": " << x << endl #define double long double const int INF = 0x3f3f3f3f ;const int MOD = 1000000007 ;const int N = 2e5 + 10 ;string s; map<char , int > mp; int a[8 ];signed main () { cin >> s; mp['a' ] = 1 ; mp['t' ] = 2 ; mp['c' ] = 3 ; mp['o' ] = 4 ; mp['d' ] = 5 ; mp['e' ] = 6 ; mp['r' ] = 7 ; for (int i = 0 ; i < 7 ; i++) a[i + 1 ] = mp[s[i]]; int res = 0 ; for (int i = 1 ; i <= 7 ; i++) { for (int j = i + 1 ; j <= 7 ; j++) if (a[j] < a[i]) res++; } cout << res << endl; return 0 ; }
显然并不需要在线查询,此时考虑倒序处理,即把删边的操作转化为连边。
此时,分一下情况:
当前两个顶点都没有电,直接连边 当前两个顶点都有电,直接连边 当前两个顶点有且仅有一个有电,向没电的方向搜索,直到都有电 时间复杂度O ( E + N ) O(E+N) O ( E + N )
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i, x, y) for (int i = x; i <= y; i++) #define repp(i, x, y) for (int i = x; i >= y; i--) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define debug(x) cerr << #x << ": " << x << endl #define double long double const int INF = 0x3f3f3f3f ;const int MOD = 1000000007 ;const int N = 2e5 + 10 ;const int M = 5e5 + 10 ;int n, m, e;int u[M], v[M];int q;int t[M];bool d[M];bool ele[N];int res = 0 ;int ans[M];vector<int > g[N]; void dfs (int x, int fa) { if (ele[x]) return ; ele[x] = true ; res++; for (auto v : g[x]) if (v != fa) dfs (v, x); } signed main () { cin >> n >> m >> e; for (int i = 1 ; i <= e; i++) cin >> u[i] >> v[i]; for (int i = n + 1 ; i <= n + m; i++) ele[i] = true ; cin >> q; for (int i = 1 ; i <= q; i++) cin >> t[i], d[t[i]] = true ; for (int i = 1 ; i <= e; i++) { if (d[i]) continue ; if (u[i] <= n && v[i] <= n) { g[u[i]].pb (v[i]); g[v[i]].pb (u[i]); } } for (int i = 1 ; i <= e; i++) { if (d[i]) continue ; if (ele[u[i]]) dfs (v[i], u[i]); else if (ele[v[i]]) dfs (u[i], v[i]); g[u[i]].pb (v[i]); g[v[i]].pb (u[i]); } for (int i = q; i >= 1 ; i--) { ans[i] = res; if (ele[u[t[i]]]) dfs (v[t[i]], u[t[i]]); if (ele[v[t[i]]]) dfs (u[t[i]], v[t[i]]); g[u[t[i]]].pb (v[t[i]]); g[v[t[i]]].pb (u[t[i]]); } for (int i = 1 ; i <= q; i++) cout << ans[i] << endl; return 0 ; }
这个东西其实可以用并查集维护,考场先写的这个,但是调假了。。。
感谢k t q \color{red}{ktq} k t q 巨佬写的代码 ,证明这个思路是真的。。。
速度比对
dp
d p i , j , 0 / 1 , 0 / 1 dp_{i,j,0/1,0/1} d p i , j , 0 / 1 , 0 / 1 分别表示当前的格子为( i , j ) (i,j) ( i , j ) ,行有没有反转过,列有没有反转过
转移很明显(见代码)
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 #include <bits/stdc++.h> using namespace std;#define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define rep(i, x, y) for (int i = x; i <= y; i++) #define repp(i, x, y) for (int i = x; i >= y; i--) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define debug(x) cerr << #x << ": " << x << endl #define double long double const int INF = 0x3f3f3f3f ;const int MOD = 1000000007 ;const int N = 2e5 + 10 ;int n, m;int r[2005 ], c[2005 ], ans;bool a[2005 ][2005 ], vis[2005 ][2005 ];int dp[2005 ][2005 ][2 ][2 ];void chkmin (int &x, int y) { if (y < x) x = y; } signed main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) cin >> r[i]; for (int i = 1 ; i <= m; i++) cin >> c[i]; for (int i = 1 ; i <= n; i++) { string s; cin >> s; for (int j = 1 ; j <= m; j++) { a[i][j] = s[j - 1 ] - '0' ; } } memset (dp, 0x3f , sizeof (dp)); dp[1 ][1 ][0 ][0 ] = 0 ; dp[1 ][1 ][1 ][0 ] = r[1 ]; dp[1 ][1 ][0 ][1 ] = c[1 ]; dp[1 ][1 ][1 ][1 ] = r[1 ] + c[1 ]; for (int i = 1 ; i <= n; i++) { for (int j = 1 ; j <= m; j++) { if (i != 1 ) { if (a[i][j] == a[i - 1 ][j]) { chkmin (dp[i][j][0 ][0 ], dp[i - 1 ][j][0 ][0 ]); chkmin (dp[i][j][1 ][0 ], dp[i - 1 ][j][1 ][0 ] + r[i]); chkmin (dp[i][j][0 ][1 ], dp[i - 1 ][j][0 ][1 ]); chkmin (dp[i][j][1 ][1 ], dp[i - 1 ][j][1 ][1 ] + r[i]); } else { chkmin (dp[i][j][0 ][0 ], dp[i - 1 ][j][1 ][0 ]); chkmin (dp[i][j][1 ][0 ], dp[i - 1 ][j][0 ][0 ] + r[i]); chkmin (dp[i][j][0 ][1 ], dp[i - 1 ][j][1 ][1 ]); chkmin (dp[i][j][1 ][1 ], dp[i - 1 ][j][0 ][1 ] + r[i]); } } if (j != 1 ) { if (a[i][j - 1 ] == a[i][j]) { chkmin (dp[i][j][0 ][0 ], dp[i][j - 1 ][0 ][0 ]); chkmin (dp[i][j][0 ][1 ], dp[i][j - 1 ][0 ][1 ] + c[j]); chkmin (dp[i][j][1 ][0 ], dp[i][j - 1 ][1 ][0 ]); chkmin (dp[i][j][1 ][1 ], dp[i][j - 1 ][1 ][1 ] + c[j]); } else { chkmin (dp[i][j][0 ][0 ], dp[i][j - 1 ][0 ][1 ]); chkmin (dp[i][j][0 ][1 ], dp[i][j - 1 ][0 ][0 ] + c[j]); chkmin (dp[i][j][1 ][0 ], dp[i][j - 1 ][1 ][1 ]); chkmin (dp[i][j][1 ][1 ], dp[i][j - 1 ][1 ][0 ] + c[j]); } } } } cout << min (min (dp[n][m][0 ][0 ], dp[n][m][0 ][1 ]), min (dp[n][m][1 ][0 ], dp[n][m][1 ][1 ])) << endl; return 0 ; }