思路:
平衡树,遍历整个数组,维护从 1 到 i(或者从 n 到 i)的数从小到大排序,然后维护其差分,维护差分数组中每个值出现了多少次,再维护有多少个数出现在差分数组中。
平衡树用 pb_ds 实现。(本蒟蒻太菜以至于只会这个,不知道会不会变慢?)
代码:
#include<ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
#include<bits/stdc++.h>
using namespace std;
struct balanced_tree{
tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> t;
void cl(){
t.clear();
}
void ins(int x){
t.insert(x);
}
int sz(){
return t.size();
}
int ord(int x){
return t.order_of_key(x)+1;
}
int bk(int x){
auto it=t.lower_bound(x);
it--;
return *it;
}
int ne(int x){
auto it=t.upper_bound(x);
return *it;
}
}t;
inline int read(){
int re=0;
char ch=getchar();
while(ch>='0'&&ch<='9') re=(re*10)+ch-48,ch=getchar();
return re;
}
int q,n,a[1000100],ans,cnt;
bool r[1000100];
map<int,int> m;
int main(){
q=read();
while(q--){
n=read();
ans=cnt=0;
for(int i=1;i<=n;i++){
a[i]=read();
t.ins(a[i]);
int v=t.ord(a[i]);
if(i==1){
r[i]=1;
continue;
}
if(v==1){
int u=t.ne(a[i]);
if(m[u-a[i]]++==0) cnt++;
}
else if(v==t.sz()){
int u=t.bk(a[i]);
if(m[a[i]-u]++==0) cnt++;
}
else{
int x=t.bk(a[i]),y=t.ne(a[i]);
if(--m[y-x]==0) cnt--;
if(m[y-a[i]]++==0) cnt++;
if(m[a[i]-x]++==0) cnt++;
}
if(cnt==1) r[i]=1;
}
m.clear();
t.cl();
cnt=0;
for(int i=n;i>=2;i--){
t.ins(a[i]);
int v=t.ord(a[i]);
if(i==n){
if(r[i-1]==1) ans++;
continue;
}
if(v==1){
int u=t.ne(a[i]);
if(m[u-a[i]]++==0) cnt++;
}
else if(v==t.sz()){
int u=t.bk(a[i]);
if(m[a[i]-u]++==0) cnt++;
}
else{
int x=t.bk(a[i]),y=t.ne(a[i]);
if(--m[y-x]==0) cnt--;
if(m[y-a[i]]++==0) cnt++;
if(m[a[i]-x]++==0) cnt++;
}
if(cnt==1&&r[i-1]==1) ans++;
}
m.clear();
t.cl();
for(int i=1;i<=n;i++){
r[i]=0;
}
printf("%d\n",ans);
}
}