pro:给出n, k和长度为n的数组a, 两个人轮流取数1先取,设a[i]是当前数组中最大值,则取走a[i - k]到a[i + k]这段数,然后把a[i + k + 1]和后面的补到 a[i - k]的位置。(当然要考虑前后边界,i - k不能小于1,i + k不能大于n)输出一个字符串s[i]表示a[i]属于1或2;
sol:要解决的就是把a[i + k + 1]后面的往前移的操作,可以不用移,建两个数组,lft[i]表示i的上一个数下标,rgt[i]表示i下一个数的下标。
- 有点像HDU1698用并查集解决的骚操作,都是标记上一个数或下一个数
E - Two Teams GNU C++11 Accepted 46 ms 3300 KB #include "bits/stdc++.h" using namespace std; const int MAXN = 2e5 + 5; int a[MAXN], b[MAXN], lft[MAXN], rgt[MAXN]; char ans[MAXN]; int n, k, d = 1; void del(int t) { ans[t] = d ^ '0'; lft[rgt[t]] = lft[t]; rgt[lft[t]] = rgt[t]; } int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[a[i]] = i; lft[i] = i - 1; rgt[i] = i + 1; } for (int i = n; i >= 1; i--) { int m = b[i]; if (ans[m]) continue; del(m); m = lft[m]; for (int j = 0; j < k && m >= 1; j++) del(m), m = lft[m]; m = rgt[m]; for (int j = 0; j < k && m <= n; j++) del(m), m = rgt[m]; d = 3 - d; } puts(ans + 1); return 0; }
C++真好用,看到有人用STL里的东西来暴力,1900+ms卡过去了。本来想尝试hack一下的,数据太大无法提交。