bool vis[maxn]; voidsolve(){ memset(vis, 0, sizeof vis); int n, k; cin >> n >> k; if (2 * k - n == n) { for (int i = 1; i <= n; ++i) cout << i << ' '; cout << endl; return; } for (int i = k - 1; i >= 2 * k - n; --i) //标记这些在 k 前面重复的数 vis[i] = 1; for (int i = 1; i <= k; ++i) { if (vis[i]) continue; //不输出这些数 cout << i << ' '; } for (int i = k - 1; i >= 2 * k - n; --i) cout << i << ' '; cout << endl; }
signedmain(){ ios::sync_with_stdio(false), cin.tie(0); int t; cin >> t; while (t--) { solve(); } // system("pause"); return0; }
题意:起初 x 的值是 0,给出一个长度为 n 的操作串,其中 + 代表将当前的 x 加 1,- 代表将当前的 x 减 -1。然后有 m 次询问,每次询问会产出操作串 [l,r] 区间的操作,请你计算出执行剩下的操作过程中 x 总共变成了多少个不同的值
思路:佩服自己训练的时候暴力模拟也敢往上写 😅。因为询问只考虑 x 的不同变化范围所以正确的方法是统计操作过程中出现的最大值和最小值,那么答案就是 maxx-minn+1,但是模拟遍历肯定是不行的会 TLE。考虑分别统计出前后缀区间 [1,i]和[i,n] 的最大值和最小值,如此删除区间 [l,r] 后最值一定是从剩余左右两个区间的最值中取出来,时间复杂度为O(1),但是右区间由于缺少了删除区间的操作的 x 的变化范围整体发生改变,那么如何确定变化的数值用前缀和求出就可以了,同时借助前缀和也可以帮助我们计算出每个操作后当前 x 的值的同时顺便求出上述需要统计的前后缀区间的最大值和最小值
最后找答案的时候需要注意两个特殊情况:剩下区间全是左区间或者剩下区间全是右区间,另外还需要注意的细节是 x 起初还有个取值 0