题解 CF1288E 【Messenger Simulator】
正解是个很有创造力的做法,感觉自己get了不少。两个月没碰OI水平果然大幅度下降了。
首先我们一看,这是个把数往数组开头怼的序列问题。因为移动数组中元素是个非常麻烦的事情,我们在数组的左端添加
我们把实际上没有放数的点设为
这样我们只需要查询在一个点前面有多少个
因为最小值只可能是
然后我们就很愉快地解决了这个问题。
代码非常好写,自认为思路比楼下小哥清晰不少。
const int MAXN = 600005;
int n, m, mini[MAXN], maxi[MAXN], c[MAXN], pos[MAXN];
void update(int x, int v) {for(; x <= n+m; x += (x&-x)) c[x] += v;}
int query(int x) {int ans = 0;for(; x; x -= (x&-x)) ans += c[x];return ans;}
signed main()
{
cin >> n >> m;
For(i, 1, n) mini[i] = maxi[i] = i, pos[i] = m+i, update(pos[i], 1);
int now = m;
For(k, 1, m) {
int i = read(); mini[i] = 1;
ckmax(maxi[i], query(pos[i]));
update(pos[i], -1);
pos[i] = now--;
update(pos[i], 1);
}
For(i, 1, n) ckmax(maxi[i], query(pos[i]));
For(i, 1, n) printf("%d %d\n", mini[i], maxi[i]);
return 0;
}