题解:同一个位置的访问时间是 time = i - 1 + k * n(每秒向前移动一步,初始时刻是0),从每个位置的出去时间满足( i - 1 + k * n >= a[ i ] ),然后解出满足不等式的最小的k,代入( i - 1 + k * n),就是从该位置出去的时刻,那么答案就是所有位置中出去时间最早的位置。因为time的大小只和k有关,所以可以直接比较k的大小。
PS:2000人的题FST了,真是气啊。除法中向上取整,分母加上 n - 1,避免判断!!!!!
#include<bits/stdc++.h> #define ll long long #define P pair<int,int> #define pb push_back #define lson root << 1 #define INF (int)2e9 + 7 #define maxn (int)1e5 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n; int a[maxn]; int main() { cin >> n; int res = INF, ans; for(int i = 1; i <= n; i++){ cin >> a[i]; int y = (a[i] - i + n) / n; if(res > y){ res = y; ans = i; } } cout << ans << endl; return 0; }
PS:官方的题解太妙了,将中间两行看成一个循环,一个数移动 2n次,必定访问到这个循环的所有位置,所以暴力枚举就行了,在10000的范围内肯定能做完。如果要求最少移动步数就不知道怎么做了
#include<bits/stdc++.h> #define ll long long #define P pair<int, int> #define PP pair<int,pair<int, int>> #define pb push_back #define pp pop_back #define lson root << 1 #define INF (int)2e9 + 7 #define maxn (int)1e5 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n, k, cnt; int mp[5][55]; P add[200]; vector<PP> v; void Inite() { cnt = 0; for(int i = 1; i <= n; i++) add[++cnt] = P(2, i); for(int i = n; i >= 1; i--) add[++cnt] = P(3, i); } int main() { cin >> n >> k; Inite(); for(int i = 1; i <= 4; i++) for(int j = 1; j <= n; j++) cin >> mp[i][j]; bool flag = false; for(int i = 1; i <= n; i++) { P x = P(1, i), y = P(4, i); if(mp[1][i] == mp[2][i] && mp[1][i]) { v.pb(PP(mp[2][i], x)); mp[2][i] = 0; } if(mp[3][i] == mp[4][i] && mp[3][i]) { v.pb(PP(mp[3][i], y)); mp[3][i] = 0; } if(!mp[2][i] || !mp[3][i]) flag = true; } if(!flag) { puts("-1"); return 0; } //cout << endl; for(int t = 1; t <= 20000; t++) { /* for(int i = 1; i <= 4; i++) { for(int j = 1; j <= n; j++) { cout << mp[i][j] << " "; } cout << endl; } cout << endl; */ // 枚举每次循环的起始位置 int pos; for(int i = 1; i <= cnt; i++) { P tp = add[i]; if(mp[tp.first][tp.second] == 0){ pos = i; break; } } // 将整个环移动一个位置 for(int i = 0; i < cnt; i++) { int now = (pos - i <= 0 ? pos - i + cnt : pos - i); int pre = (now == 1 ? cnt : now - 1); //cout << now << " " << pre << endl; if(i == cnt - 1){ mp[add[now].first][add[now].second] = 0; continue; } P x, y; x = add[now]; y = add[pre]; mp[x.first][x.second] = mp[y.first][y.second]; if(mp[y.first][y.second]) v.pb(PP(mp[y.first][y.second], x)); } for(int i = 1; i <= n; i++) { P x = P(1, i), y = P(4, i); if(mp[1][i] == mp[2][i] && mp[1][i]) { v.pb(PP(mp[2][i], x)); mp[2][i] = 0; } if(mp[3][i] == mp[4][i] && mp[3][i]) { v.pb(PP(mp[3][i], y)); mp[3][i] = 0; } } } int res = (int)v.size(); cout << (res == 0 ? -1 : res) << endl; for(auto i : v) { P tp = i.second; cout << i.first << " " << tp.first << " " << tp.second << endl; } return 0; }
PS:又是一道不知道怎么证明的题,比赛的时候2000人过,真是,,,难受! Orz,我们可以从最左的位置开始考虑,对于第一个数来说,它的另一半向左移比它向右移会更优,注意第一个数的位置在最左端,所以它向右移的话必定会增加其他对的移动步数。处理完第一对后,剩下的同样处理。
#include<bits/stdc++.h> #define ll long long #define P pair<int, int> #define PP pair<int,pair<int, int>> #define pb push_back #define pp pop_back #define lson root << 1 #define INF (int)2e9 + 7 #define maxn (int)1e5 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; int n; int a[300]; int main() { cin >> n; int m = 2 * n; for(int i = 1; i <= m; i++) cin >> a[i]; int res = 0; for(int i = 1; i <= m; i += 2) { int pos = -1; for(int j = i + 1; j <= m; j++) if(a[j] == a[i]) { pos = j; break; } for(int j = pos; j > i + 1; j--) { swap(a[j], a[j - 1]); res++; } } cout << res << endl; return 0; }
PS:多生成几次随机序列然后贪心都能过,不知道为啥
// 调换一下循环的顺序就会WA
#include<bits/stdc++.h> #define ll long long #define P pair<int, int> #define PP pair<int,pair<int, int>> #define pb push_back #define pp pop_back #define lson root << 1 #define INF (int)2e9 + 7 #define maxn (int)1e5 + 7 #define rson root << 1 | 1 #define LINF (unsigned long long int)1e18 #define mem(arry, in) memset(arry, in, sizeof(arry)) using namespace std; P a[maxn]; int n, c[maxn]; ll dis(ll x, ll y) { return sqrt(x * x + y * y); } int main() { cin >> n; for(int i = 0; i < n; i++) cin >> a[i].first >> a[i].second; int x = 0, y = 0; for(int i = n - 1; i >= 0; i--) { if(dis(x + a[i].first, y + a[i].second) <= dis(x - a[i].first, y - a[i].second)) { x += a[i].first; y += a[i].second; c[i] = 1; } else{ x -= a[i].first; y -= a[i].second; c[i] = -1; } } for(int i = 0; i < n; i++) cout << c[i] << " "; cout << endl; return 0; }