集训学了些妙妙的数据结构和晕晕的知识(线性基)。
qaq代码里注释解释的很清楚了。。再详细的见:
会施放魔法的小女巫打开的传送门
静态区间第K大离散化不去重主席树模板
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,m;
struct node{
int l,r,sum;
}T[MAXN*60];
struct A{
int x,idx;
bool operator<(const A&rhs)const{
return x<rhs.x;
}
}a[MAXN];
int rk[MAXN],rt[MAXN],cnt;
void insert(int num,int &p,int l,int r){
T[cnt++]=T[p];p=cnt-1;
T[p].sum++;
if(l==r)return;
int mid=(l+r)>>1;
if(num<=mid)insert(num,T[p].l,l,mid);//在l-r(离散化后的数据范围里查找)
else insert(num,T[p].r,mid+1,r);
}
int query(int i,int j,int k,int l,int r){
if(l==r)return l;
int mid=(l+r)>>1,tem=T[T[j].l].sum-T[T[i].l].sum;
if(k<=tem)return query(T[i].l,T[j].l,k,l,mid);
else return query(T[i].r,T[j].r,k-tem,mid+1,r);
}
int main(){
T[0].l=T[0].r=T[0].sum=0;//空节点
rt[0]=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].x);
a[i].idx=i;//记录原数列序列号
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)rk[a[i].idx]=i;//把序列号映射到rk数组 rk的值(序列位置离散化以后的值)
cnt=1;
for(int i=1;i<=n;i++){
rt[i]=rt[i-1];
insert(rk[i],rt[i],1,n);//为原序列 建线段树,值域1-n是因为没有去重,一共离散化了n个数。
}
while(m--){
int i,j,k;
scanf("%d",&i);
printf("%d %d\n",T[rt[i]].sum,T[rt[i]].l);
}
return 0;
}