小卡家有N只狗,由于品种、年龄不同,每一只狗都有一个不同的漂亮值。漂亮值与漂亮的程度成反比(漂亮值越低越漂亮),吃饭时,狗狗们会按顺序站成一排等着主人给食物。
可是嘉嘉真的很懒,他才不肯喂这么多狗呢,这多浪费时间啊,于是他每次就只给第i只到第j只狗中第k漂亮的狗狗喂食(好狠心的人啊)。而且为了保证某一只狗狗不会被喂太多次,他喂的每个区间(i,j)不互相包含。
第一行输入两个数n,m,你可以假设n<300001 并且 m<50001;m表示他喂了m次。
第二行n个整数,表示第i只狗的漂亮值为ai。
接下来m行,每行3个整数i,j,k表示这次喂食喂第i到第j只狗中第k漂亮的狗的漂亮值。
题解:
就是可持久化线段树...用平衡树套线段树会TLE。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=4e5+10; int n,q,m,tot; int a[maxn]; int t[maxn]; int T[maxn]; int lson[maxn*30],rson[maxn*30],c[maxn*30]; void init_hash () { for (int i=1;i<=n;i++) t[i]=a[i]; sort(t+1,t+n+1); m=unique(t+1,t+n+1)-t-1; } int build (int l,int r) { int root=tot++; c[root]=0; if (l!=r) { int mid=(l+r)>>1; lson[root]=build(l,mid); rson[root]=build(mid+1,r); } return root; } int Hash (int x) { return lower_bound(t+1,t+m+1,x)-t; } int update (int root,int pos,int val) { int newroot=tot++,tmp=newroot; c[newroot]=c[root]+val; int l=1,r=m; while (l<r) { int mid=(l+r)>>1; if (pos<=mid) { lson[newroot]=tot++; rson[newroot]=rson[root]; newroot=lson[newroot]; root=lson[root]; r=mid; } else { rson[newroot]=tot++; lson[newroot]=lson[root]; newroot=rson[newroot]; root=rson[root]; l=mid+1; } c[newroot]=c[root]+val; } return tmp; } int query (int left_root,int right_root,int k) { int l=1,r=m; while (l<r) { int mid=(l+r)>>1; if (c[lson[left_root]]-c[lson[right_root]]>=k) { r=mid; left_root=lson[left_root]; right_root=lson[right_root]; } else { l=mid+1; k-=c[lson[left_root]]-c[lson[right_root]]; left_root=rson[left_root]; right_root=rson[right_root]; } } return l; } int main () { while (~scanf("%d%d",&n,&q)) { tot=0; for (int i=1;i<=n;i++) scanf("%d",&a[i]); init_hash(); T[n+1]=build(1,m); for (int i=n;i;i--) { int pos=Hash(a[i]); T[i]=update(T[i+1],pos,1); } while (q--) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d ",t[query(T[l],T[r+1],k)]); } } return 0; }