2021牛客寒假算法基础集训营4 D题-温澈滢的狗狗

题目链接
在这里插入图片描述
题解:

要解决这个问题,就必须得知道亲密度 ≤ \leq d的对数有多少,但不能强行算不同色有多少对,因为会超时,所以要用到容斥。即 不同色数目=所有-同色。

所有对数目 = d + d + d + . . . . + d − 1 + d − 2 + 1 + 0 =d+d+d+....+d-1+d-2+1+0 =d+d+d+....+d1+d2+1+0,可以直接算出来,要计算同色对,先把所有相同颜色的放在一起,可以用vector存一下,然后用双指针去计算出同色对数目。

接来下就是二分了,二分出第k个的亲密度是多少,知道了亲密度,直接可以 o ( n ) o(n) o(n)求出亲密度为d的所有对,然后排个序就知道第k个是什么了。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f;
int a[MAXN];
ll sum[MAXN];
std::vector<int>v[MAXN];
map<int ,int >mp;
struct node
{
    
    
    int x,y;
}f[MAXN];
bool cmp(node aa,node bb)
{
    
    
    if(aa.x==bb.x) return aa.y<bb.y;
    else return aa.x<bb.x;
}
int main()
{
    
    
    int n;ll k;
    scanf("%d%lld",&n,&k);
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
    
    
        scanf("%d",&a[i]);
        if(!mp.count(a[i]))
        {
    
    
            mp[a[i]]=++cnt;
        }
        v[mp[a[i]]].push_back(i);
    }
    for(int i=1;i<=n-1;i++)
    {
    
    
        sum[i]=1ll*(n-i)*i;
        sum[i]+=1ll*i*(i-1+0)/2;
    }
    int l=1,r=n-1;
    int pos=-1;
    ll cal;
    while(l<=r)
    {
    
    
        int mid=(l+r)>>1;
        ll ans=0;
        for(int i=1;i<=cnt;i++)
        {
    
    
            if(v[i].size()==1) continue; 
            int pos1=0,pos2=1;
            int len=v[i].size();
            while(1)
            {
    
    
                while(pos2<len&&v[i][pos2]-v[i][pos1]<=mid)
                {
    
    
                    ans+=pos2-pos1;
                    pos2++;
                }
                if(pos2==len) break;
                while(pos1<pos2&&v[i][pos2]-v[i][pos1]>mid) pos1++;
            }
        }
        ll res=sum[mid]-ans;
        if(res>=k)
        {
    
    
            pos=mid;
            cal=res;
            r=mid-1;
        }
        else l=mid+1;
    }
    if(pos==-1)
    {
    
    
        printf("-1\n");
        return 0;
    }
    int cot=0;
    for(int i=1;i+pos<=n;i++)
    {
    
    
        if(a[i]!=a[i+pos])
        {
    
    
            f[++cot].x=i;
            f[cot].y=i+pos;
        }
    }
    sort(f+1,f+cot+1,cmp);
    for(int i=1;i<=cot;i++)
    {
    
    
        if(cal-cot+i==k)
        {
    
    
            printf("%d %d\n",f[i].x,f[i].y);
            return 0;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/113874529
今日推荐