NC213854. 回音
描述
只有回音在生命中陪伴寒暄着过往
用窒息的孤独感将身躯花葬
星点的回音汇成声浪强烈的力量
将心房不断叩响
条子给了你一个序列ai,长度为n,一个长度为m的区间序列[xi,yi]。
现在有q次询问,每次询问有3个参数l,r,k。
每次询问开始,你有一个空的可重集S,然后对于每个区间[xi,yi](l <= i <= r),将axi...yi的所有数插入S中。
现在条子想知道,S中第k小的数是多少。
输入描述
第一行,三个整数n,m,q,分别表示序列a,区间序列的长度,询问次数。
第二行,n个整数ai。
后面m行,每行两个整数xi,yi。
后面q行,每行三个整数l,r,k表示一次询问。
输出描述
q行,每行一个整数,第i行表示第i次询问的答案。
示例1
输入:
8 4 3 1 4 6 2 3 4 1 5 1 4 2 4 3 6 6 8 1 4 10 2 3 3 2 4 8
输出:
4 3 5
C++(clang++11) 解法, 执行用时: 2074ms, 内存消耗: 383464K, 提交时间: 2021-01-19 21:08:32
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; const int M=450; int n,m,q,ans,a[N],x[N],y[N],be[N],v[N],sx[N],sy[N],s[N][M]; long long w[N]; struct dd { int x,y; friend bool operator <(dd a,dd b) { return a.x<b.x; } }b[N]; struct dp { int l,r; long long k; }c[N]; vector<int>g[N]; int get(int x) { return (x+M-1)/M; } void add(int l,int r) { while (l%M!=1 && l<=r) sx[l]++,l++; if (l>r) return; while (r%M!=0 && r>=l) sx[r]++,r--; if (l>r) return; for (int i=get(l);i<=get(r);i++) sy[i]++; } int ask(int x) { return sx[x]+sy[get(x)]; } int main() { scanf("%d%d%d",&n,&m,&q); for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i].x=a[i],b[i].y=i; sort(b+1,b+n+1); for (int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]); for (int i=1;i<=q;i++) scanf("%d%d%lld",&c[i].l,&c[i].r,&c[i].k); for (int i=1;i<=n;i+=M) { for (int j=1;j<=n;j++) v[j]=0; for (int j=i;j<min(i+M,n+1);j++) v[b[j].y]=1; for (int j=1;j<=n;j++) v[j]+=v[j-1]; w[0]=0; for (int j=1;j<=m;j++) w[j]=w[j-1]+v[y[j]]-v[x[j]-1]; for (int j=1;j<=q;j++) if (!be[j]) { long long p=w[c[j].r]-w[c[j].l-1]; if (c[j].k>p) c[j].k-=p; else be[j]=get(i); } } for (int i=1;i<=q;i++) { g[c[i].r].push_back(i); g[c[i].l-1].push_back(-i); } for (int i=1;i<=m;i++) { add(x[i],y[i]); for (int j=0;j<g[i].size();j++) { int u=g[i][j],f=1; if (u<0) f=-1,u=-u; int st=(be[u]-1)*M+1; for (int t=st;t<st+M && t<=n;t++) s[u][t-st+1]+=f*ask(b[t].y); } } for (int i=1;i<=q;i++) { long long p=0; for (int j=1;j<=M;j++) { p+=s[i][j]; if (p>=c[i].k) { ans=(be[i]-1)*M+j; break; } } printf("%d\n",b[ans].x); } return 0; }