题目大意
给定长为$n$的序列$A$,定义长为$k$的区间中位数为从小到大排完序后第$lfloorfrac{k}{2} floor$个数的大小。
每次询问给定$l_1,r_1,l_2,r_2$有多少个子区间满足中位数$in[l_1,r_1]$长度$in[l_2,r_2]$。
询问不超过五组。
题解
将问题提转化成中位数$leq K$,长度$in [l,r]$的子区件有多少个,答案相减即为最终答案。
发现对于每一个$A_i$,若子区间内$A_ileq K$的数量至少达到区间长度的一半即可。
那么将$A_ileq K$看做$1$,否则看做$-1$,求区间和$geq 0$,区间长度$in [l,r]$的数量即可。
这个只需要用主席树或者删电加点的树状数组维护即可。
复杂度$O(2nmlog n)$。
#include<bits/stdc++.h> #define debug(x) cerr<<#x<<" = "<<x #define sp <<" " #define el <<endl #define LL long long #define M 100020 using namespace std; int read(){ int nm=0,fh=1; char cw=getchar(); for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh; for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0'); return nm*fh; } int s[M],n,m,p[M],cnt,rt[M],bf[M<<2],nt[M<<2],c[M<<2]; void ins(int pos,int dt){for(int k=pos;k<(M<<1);k=nt[k]) c[k]+=dt;} int qry(int pos){int tt=0;for(int k=pos;k;k=bf[k]) tt+=c[k];return tt;} LL solve(int Mid,int Min_len,int Max_len){ LL res=0; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ s[i]=(p[i]<=Mid?s[i-1]+1:s[i-1]-1); int t1=i-Max_len-1,t2=i-Min_len; if(t1>=0) ins(s[t1]+M,-1); if(t2>=0) ins(s[t2]+M,1); res+=qry(s[i]+M); }return res; } int main(){ n=read(); for(int i=1;i<(M<<2);i++) bf[i]=i-(i&-i),nt[i]=i+(i&-i); for(int i=1;i<=n;i++) p[i]=read(); for(int T=read();T;--T){ int l1=read(),r1=read(),l2=read(),r2=read(); printf("%lld ",solve(r1,l2,r2)-solve(l1-1,l2,r2)); } return 0; }