温澈滢的狗狗 题解(二分+双指针)
题目链接
题目思路
首先要看清亲密度为下标差写了一年假题
然后显然是要二分亲密度的
如何计算这个小于等于这个亲密度的对数
利用容斥和用总点对数-同色对数
总点对数为\((n-x)*x+(1+x-1)*(x-1)/2\)
同色对数利用双指针求解
然后知道亲密度\(O(n)\)扫一遍即可
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e5+5,inf=0x3f3f3f3f;
const double eps=1e-3;
const ll mod=1004535809;
int n;
int a[maxn],cnt[maxn];
ll k;
ll cal(int x){
memset(cnt,0,sizeof(cnt));
ll sum=1ll*(n-x)*x+1ll*(1+x-1)*(x-1)/2;
for(int i=1;i<=n;i++){
sum-=cnt[a[i]];
cnt[a[i]]++;
if(i>x){
cnt[a[i-x]]--;
}
}
return sum;
}
signed main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int l=1,r=n,ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(cal(mid)>=k){
ans=mid;
r=mid-1;
}else{
l=mid+1;
}
}
if(ans==-1){
printf("-1\n");
return 0;
}
int pos=k-cal(ans-1);
for(int i=1;i<=n;i++){
if(i+ans<=n&&a[i+ans]!=a[i]){
pos--;
if(pos==0){
printf("%d %d\n",i,i+ans);
break;
}
}
}
return 0;
}
// 3 2 1 2 3
//6 3
//1 2 3 4 5 6
不摆烂了,写题