题解:P10995 【MX-J3-T2】Substring
题目传送门
思路
贪心、前缀和、二分。
由于查询的是子串,那么串一定连续。这时候子串排序的结果一定是按照
知道了这一点后,我们就可以先记录每个数字的位置
每次查询的时候找第一个前缀和
此时
- 子串数最大为
\Large\frac{n(n+1)}{2} ,1\le n\le 3\times 10^5 ,记得开 long long。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll read(){
ll k=0;bool flag=1;char c=getchar();
while(!isdigit(c)){if(c=='-')flag=0;c=getchar();}
while(isdigit(c)){k=(k<<1)+(k<<3)+(c^48);c=getchar();}
if(flag)return k;return -k;
}
const int N=3e5+10;
ll n,q,sum[N],id[N];
struct node{
ll x,num;//x 当前数,num 子串数量。
}a[N];
signed main(){
cin>>n>>q;
for(int i=1;i<=n;++i){
a[i]={read(),n-i+1};
id[a[i].x]=i;//记录这个数的位置。
}
sort(a+1,a+1+n,[](node a,node b){return a.x<b.x;});
for(int i=1;i<=n;++i)sum[i]=sum[i-1]+a[i].num;
while(q--){
ll k=read();
int p=lower_bound(sum+1,sum+1+n,k)-sum;
cout<<id[p]<<" "<<id[p]+k-sum[p-1]-1<<"\n";
}
return 0;
}
AC 记录