赞
踩
分析:如果[l,r]存在两个不相同的数,那么一定存在 ai != aj,且 j = i+1,即这两个数是相邻的。这样的话我们可以用前缀和预处理,然后找pre[j]>pre[l]。
正常从前往后遍历是O(n),我们还有q次查询,时间复杂度O(n2)会超时。因此我们用二分查找来进行查询,时间复杂度O(nlogn)
- int a[N], pre[N];//pre[i]表示,从a1->ai相邻不同的对数
- void solve() {
- //memset(pre, 0, sizeof pre);
- int n; cin >> n;
- rep(i, 1, n) cin >> a[i];
- rep(i, 2, n) {
- pre[i] = pre[i - 1] + (a[i] != a[i - 1]);
- }
-
- int q; cin >> q;
- while (q--) {
- int l, r; cin >> l >> r;
- //tans;
- //在pre[l,r]里二分找大于pre[l],
- //找到的第一个pre[k]>pre[l],说明有增加的对数,且为a[k-1]和a[k]
- int k = upper_bound(pre + 1 + l, pre + 1 + r, pre[l]) - pre;
- if (k > r) cout << -1 << " " << -1 << endl;
- else cout << k - 1 << " " << k << endl;
-
- }
-
- }
分析:假设一个数组a是k级排列,那么a里有n-k+1组,每组的和与其他组的和的差不大于1。
数组a = {a1,a2,a3,a4,a5,a6,...},
第一,假设k = 3,说明 |(ai+aj+ak) - (aj+ak+al)| <= 1 (ijkl是+1递增的),
等同于 |ai - al| <= 1,我们要控制好ai和al的差小于等于1就行(也就是ai比al大1,或者al比ai大1)。
第二,假设其中一组和为x,那么其他组的和只能为x或者x+1。
第三,只要在奇数位从小到大以k的间隔填入,在偶数位从大到小以k的间隔填入,就可以构造出符合题意的序列。
ps:做完这道题有一点点个人理解,我发现很多题都会在奇数和偶数上下文章。像这题的特点就是“对称性”(我便于自己理解所以这么叫),例如:ai,aj,ak,al的关键是ai和al的放置,有一点“对称”的感觉
- int a[N];
- void solve() {
- int n, k; cin >> n >> k;
- int f = 1;
- int b = n;
- for (int i = 1; i <= k; i++) {
- if (i % 2) {
- for (int j = i; j <= n; j += k) a[j] = f++;
- }
- else {
- for (int j = i; j <= n; j += k) a[j] = b--;
- }
- }
-
- //tans;
- for (int i = 1; i <= n; i++) {
- cout << a[i] << " ";
- }
- cout << endl;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。