题意:
给出一个序列,求序列中有多少个子序列(子序列要求任意两个数差值小于k)
分析:
从左到右把数字加入multiset。multiset存储子序列,
新数字与multiset里面的最大值和最小值比较,差值小于k则可以加入,
否则,按顺序出multiset直到新数字可以加入
每次新加入数字时ans+=multiset.size()
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<set>
using namespace std;
typedef long long LL;
const int MAX = 100005;
int n,k,a[MAX];
multiset<int>st;
void solve()
{
st.clear();
int s=0,e=0;LL ans=0;
for(;s<n&&e<n;){
//可加入新数字
while( e<n && ( st.empty()||(*st.begin()>a[e]-k&&*st.rbegin()<a[e]+k) )){
ans+=(LL)st.size();///计数
st.insert(a[e]); ///插入
e++;
}
///按顺序出multiset直到新数字能加进去
while( s<n && !st.empty() &&!(*st.begin()>a[e]-k&&*st.rbegin()<a[e]+k) ){
st.erase(st.find(a[s]));///按顺序删除
s++;
}
}
printf("%I64d\n",ans+n); ///加上每个数字单独成为一个子序列
}
int main()
{
int T;
for(scanf("%d",&T); T--;){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
if(k==0){printf("0\n");continue;}
solve();
}
return 0;
}