题目
https://ac.nowcoder.com/acm/contest/9984/D
思路
- 关键:如何遍历? 如:按亲密关系遍历,按亲密度值分类后遍历,按亲密度值上界分类再遍历等等。
- 按亲密度值上界分类,则上界越大,亲密度关系越多,有单调递增特性
- 对于给定的k值,通过二分搜索,可确定第k个亲密关系所处的上界值
- 然后再细化到编号i,j的值
- 按亲密度值上界分类时,每一类中所含的亲密关系数量通过滑动窗口的方式计算。先取从1开始的第一个窗口,遍历该窗口内的每个元素,该窗口内同种颜色之间不存在亲密关系,统计各颜色的数量的同时排除非亲密关系;然后滑动窗口,每次滑动1个位置,直到最后一个元素。每次滑动,只有首尾元素变化,仅计算增量部分即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
long long c[MAXN], sum[MAXN], tot, tmp, k;
int main(){
int n, l, r, mid;
scanf("%d %lld", &n, &k);
for(int i = 1; i <= n; i++) scanf("%d", c+i);
l = 0, r = n+1;
while(r > l+1){
memset(sum, 0, sizeof sum), tmp = 0;
mid = (l + r) / 2;
for(int i = 1; i <= mid; i++)
++sum[c[i]], tmp += i - sum[c[i]];
for(int i = mid+1; i <= n; i++)
++sum[c[i]], --sum[c[i-mid]], tmp += mid - sum[c[i]];
if(tmp >= k)
r = mid, tot = tmp;
else
l = mid;
}
if(l == n) {
printf("-1\n");
return 0;
}
for(int i = n; i >= 1 ; i--){
if(c[i] == c[i-r+1]) continue;
if(tot == k){
printf("%d %d\n", i-r+1, i);
break;
}
else tot--;
}
return 0;
}