归并树:
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<cmath> #include<set> #include<stack> #define ll long long #define max(x,y) (x)>(y)?(x):(y) #define min(x,y) (x)>(y)?(y):(x) #define cls(name,x) memset(name,x,sizeof(name)) using namespace std; const int inf=1<<28; const int maxn=50010; const int maxm=110; const int mod=1e9+7; const double pi=acos(-1.0); int n; struct node { int *num; int len; }tree[maxn*4]; int num[maxn]; void build(int l,int r,int x) { tree[x].len=r-l+1; tree[x].num=new int[tree[x].len]; if(l==r) { tree[x].num[0]=num[l]; return ; } int mid=(l+r)/2; build(l,mid,x*2); build(mid+1,r,x*2+1); int i=0,j=0,k=0; while(i<tree[x*2].len&&j<tree[x*2+1].len) { if(tree[x*2].num[i]<tree[x*2+1].num[j]) tree[x].num[k++]=tree[x*2].num[i++]; else tree[x].num[k++]=tree[x*2+1].num[j++]; } while(i<tree[x*2].len) tree[x].num[k++]=tree[x*2].num[i++]; while(j<tree[x*2+1].len) tree[x].num[k++]=tree[x*2+1].num[j++]; } int querry(int ql,int qr,int temp,int l,int r,int x) { if(ql==l&&qr==r) { int tl=0,tr=tree[x].len; while(tl<tr) { int mm=(tl+tr)/2; if(tree[x].num[mm]<temp) tl=mm+1; else tr=mm; } return tl; } int mid=(l+r)/2; if(qr<=mid) return querry(ql,qr,temp,l,mid,x*2); else if(ql>=mid+1) return querry(ql,qr,temp,mid+1,r,x*2+1); else return querry(ql,mid,temp,l,mid,x*2)+querry(mid+1,qr,temp,mid+1,r,x*2+1); } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,n,1); int q; scanf("%d",&q); while(q--) { int a,b,c; scanf("%d%d%d",&a,&b,&c);//k有b-a-c个小于它的数 int l=1,r=n; while(l<r) { int mid=(l+r)/2; int qc=querry(a+1,b+1,tree[1].num[mid],1,n,1); if(qc<=b-a-c+1) l=mid; else r=mid; if(l+1==r) break; } if(querry(a+1,b+1,tree[1].num[r],1,n,1)==b-a-c+1) printf("%d\n",tree[1].num[r]); else printf("%d\n",tree[1].num[l]); } } return 0; }
划分树:
#include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<cmath> #include<set> #include<stack> #define ll long long #define pb push_back #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)>(y)?(y):(x)) #define cls(name,x) memset(name,x,sizeof(name)) #define fs first #define sc second #define mp make_pair #define L(x) (1<<x) #define next Next using namespace std; const int inf=1e9+10; const ll llinf=1e16+10; const int maxn=4e5+10; const int maxm=1e3+10; const int mod=1e9+7; int n,m; struct node { int *num; int *c;//[l,i]有多少个数进入左子树 }tree[maxn*4]; int sorted[maxn]; void init(int l,int r,int x) { tree[x].num=new int[r-l+2]; tree[x].c=new int[r-l+2]; tree[x].c[0]=0; if(l==r) return ; int mid=(l+r)/2; init(l,mid,x*2); init(mid+1,r,x*2+1); } void build(int l,int r,int x)//必须是稳定的快排 { if(l==r) return ; int mid=(l+r)/2; int key=sorted[mid]; int k1=0,k2=0;//进入左右子树的数量 int c=0;//小于key必进入左子树数量 for(int i=1;i<=r-l+1;i++) if(tree[x].num[i]<key) c++; c=mid-l+1-c;//等于key可进入左子树数量 for(int i=1;i<=r-l+1;i++) { if(tree[x].num[i]<key) tree[x*2].num[1+k1++]=tree[x].num[i]; else if(tree[x].num[i]==key) { if(c) { tree[x*2].num[1+k1++]=tree[x].num[i]; c--; } else tree[x*2+1].num[1+k2++]=tree[x].num[i]; } else tree[x*2+1].num[1+k2++]=tree[x].num[i]; tree[x].c[i]=k1; } build(l,mid,x*2); build(mid+1,r,x*2+1); } int query(int ql,int qr,int k,int l,int r,int x)//返回[ql,qr]第k小的数 { if(l==r) return tree[x].num[1]; int cl=tree[x].c[qr-l+1]-tree[x].c[ql-1-l+1];//[ql,qr]中有多少进入了左子树 int cr=qr-ql+1-cl;//[ql,qr]中有多少进入了右子树 int mid=(l+r)/2; int tl=tree[x].c[ql-1-l+1]-tree[x].c[l-1-l+1];//[l,ql-1]中有多少进入了左子树 int tr=ql-1-l+1-tl;//[l,ql-1]中有多少进入了右子树 if(k<=cl) return query(l+tl,l+tl+cl-1,k,l,mid,x*2); else return query(mid+1+tr,mid+1+tr+cr-1,k-cl,mid+1,r,x*2+1); } int cquery(int ql,int qr,int k,int l,int r,int x)//返回[ql,qr]小于等于k的数量 { if(l==r) { if(tree[x].num[1]<=k) return 1; else return 0; } int cl=tree[x].c[qr-l+1]-tree[x].c[ql-1-l+1];//[ql,qr]中有多少进入了左子树 int cr=qr-ql+1-cl;//[ql,qr]中有多少进入了右子树 int mid=(l+r)/2; int tl=tree[x].c[ql-1-l+1]-tree[x].c[l-1-l+1];//[l,ql-1]中有多少进入了左子树 int tr=ql-1-l+1-tl;//[l,ql-1]中有多少进入了右子树 if(sorted[mid]<=k) return cl+cquery(mid+1+tr,mid+1+tr+cr-1,k,mid+1,r,x*2+1); else return cquery(l+tl,l+tl+cl-1,k,l,mid,x*2); } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) scanf("%d",&sorted[i]); init(1,n,1);//内存分配 for(int i=1;i<=n;i++) tree[1].num[i]=sorted[i]; sort(sorted+1,sorted+1+n); build(1,n,1); scanf("%d",&m); while(m--) { int a,b,c; scanf("%d %d %d",&a,&b,&c); printf("%d\n",query(a+1,b+1,b-a+1-c+1,1,n,1)); } } return 0; }