【Henu ACM Round#19 D】 Points on Line

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

考虑l..r这个区间。 且r是满足a[r]-a[l]<=d的最大的r

如果是第一个找到的区间,则直接累加C(r-l+1,3);
然后l++

然后考虑这个区间之后的下一个区间[l+1,R],这里R是满足a[R]-a[l+1]<=d的最大的R

如果R==r的话,l=l+1,continue;

否则。
如果l+1>r的话累加C(R-(l+1)+1,3);
如果l+1<=r的话
显然l..r和l+1..R之间有一个公共的部分[l+1..r]以及第二个区间独立的部分[r+1..R]
枚举i从0..2然后从第一个公共部分中取出i个位置,然后从第二个独立的部分中取出3-i个位置就好
这样可以保证不会和之前取的3元组重复
然后l=l+1,continue

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1e5;

int n,d,a[N+10];

ll xuan(int l,int r,int x){
    ll len = r-l+1;
    if (x>len) return 0;
    if (x==0) return 1;
    if (x==1){
        return len;
    }
    if (x==2)
        return len*(len-1)/2;
    else
        return len*(len-1)*(len-2)/6;
}

int main()
{
    #ifdef LOCAL_DEFINE
        freopen("rush_in.txt","r",stdin);
    #endif
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n>>d;
    for (int i=1;i <=n;i++) cin >> a[i];
    if (n<3){
        cout<<0<<endl;
        return 0;
    }
    int l = 1,r = 2,prer=-1;
    long long ans = 0;
    while (1){
        if (r<=l) r = l + 1;
        if (l==n-1) break;
        while (r+1<=n && a[r+1]-a[l]<=d) r++;
        if (a[r]-a[l]<=d){
            if (prer==-1){
                ans = ans + xuan(l,r,3);
            }else{
                if (prer<r){
                    if (l>prer){
                        ans+=xuan(l,r,3);
                    }else{
                        for (int i = 0;i <= 2;i++)
                            ans+=xuan(l,prer,i)*xuan(prer+1,r,3-i);
                    }
                }
            }
            prer = r;
        }
        l++;
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/8398272.html