点名
【题目描述】
在 J 班的体育课上,同学们常常会迟到几分钟,但体育老师的点名却一直很准时。
老师只关心同学的身高,他会依次询问当前最高的身高,次高的身高,第三高的身高,
等等。在询问的过程中,会不时地有人插进队伍里。你需要回答老师每次的询问。
【输入格式】
第一行两个整数 n m,表示先后有 n 个人进队,老师询问了 m 次
第二行 n 个整数,第 i 个数 Ai 表示第 i 个进入队伍的同学的身高为 Ai
第三行 m 个整数,第 j 个数 Bj 表示老师在第 Bj 个同学进入队伍后有一次询问
【输出格式】
m 行,每行一个整数,依次表示老师每次询问的答案。数据保证合法
【样例输入】
7 4
9 7 2 8 14 1 8
1 2 6 6
【样例输出】
9
9
7
8
【样例解释】
(9){No.1 = 9}; (9 7){No.2 = 9}; (9 7 2 8 14 1){No.3 = 7; No.4 = 8}
【数据范围】
40%的数据保证 n ≤ 1000
100%的数据保证 1 ≤ m ≤ n ≤ 30000; 0 ≤ Ai < 232
//又是主席树模板啊,最喜欢这样的题了! //换种写法 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define maxn 30010 #define maxm 1000010 using namespace std; ll n,m,cnt,num,a[maxn],root[maxn],order[maxn]; struct node{ ll lc,rc,sum; }t[maxm*5]; ll Build(ll S,ll L,ll R) { ll k=++cnt; t[k].sum=S; t[k].lc=L;t[k].rc=R; return k; } void insert(ll &root,ll pre,ll pos,ll l,ll r) { root=Build(t[pre].sum+1,t[pre].lc,t[pre].rc); if(l==r)return; ll mid=(l+r)/2; if(pos<=mid)insert(t[root].lc,t[pre].lc,pos,l,mid); else insert(t[root].rc,t[pre].rc,pos,mid+1,r); } ll Query(ll L,ll R,ll pos,ll l,ll r) { if(l==r)return l; ll sum=t[t[R].lc].sum-t[t[L].rc].sum; ll mid=(l+r)/2; if(sum>=pos)return Query(t[L].lc,t[R].lc,pos,l,mid); else return Query(t[L].rc,t[R].rc,pos-sum,mid+1,r); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); order[i]=a[i]; } sort(order+1,order+n+1); num=unique(order+1,order+n+1)-order-1; for(int i=1;i<=n;i++) { ll pos=lower_bound(order+1,order+num+1,a[i])-order; insert(root[i],root[i-1],pos,1,num); } ll l,r,k; for(int i=1;i<=n;i++) { l=1;scanf("%lld",&r);k=i; ll p=Query(root[l-1],root[r],k,1,num); printf("%lld\n",order[p]); } return 0; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。