温澈滢的狗狗 题解(二分+双指针)

题目链接

题目思路

首先要看清亲密度为下标差写了一年假题

然后显然是要二分亲密度的

如何计算这个小于等于这个亲密度的对数

利用容斥和用总点对数-同色对数

总点对数为\((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

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14427194.html