2020牛客NOIP赛前集训营-提高组(第五场)C-经典字符串问题

本文介绍如何使用主席树解决区间第K大问题,通过字符串离散化处理,实现高效查询。提供了完整的C++代码实现及详细的注释说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Statement

Solution

  • 我们对每个字符串离散化,就是一道静态区间第k大裸题
  • 需要用到可持久化线段树—主席树(模板)
  • 附上自己的模板
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#define ll long long
const int N=1e5+10,M=N<<5;
using namespace std;
int l[M],r[M],v[M],rt[N],tot;
struct node{string s;int id;}a[N];
int val[N];
int build(int a,int b)
{
	int x=++tot;
	if(a==b) return x;
	int mid=a+b>>1;
	l[x]=build(a,mid);
	r[x]=build(mid+1,b);
	return x;
}
int modify(int x,int a,int b,int p,int c)
{
	int y=++tot;
	v[y]=v[x]+c;
	if(a==b) return y;
	int mid=a+b>>1;
	if(mid>=p) l[y]=modify(l[x],a,mid,p,c),r[y]=r[x];
	else l[y]=l[x],r[y]=modify(r[x],mid+1,b,p,c);
	return y;
}
int query(int x,int y,int k,int a,int b)
{
	if(a==b) return a;
	int mid=a+b>>1;
	if(v[l[x]]-v[l[y]]>=k) return query(l[x],l[y],k,a,mid);
	else return query(r[x],r[y],k-(v[l[x]]-v[l[y]]),mid+1,b);
}
bool cmp(const node &x,const node &y){return x.s<y.s;}
int main()
{
	ios::sync_with_stdio(false);
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i].s,a[i].id=i;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++) val[a[i].id]=i;
	rt[n+1]=build(1,n);
	for(int i=n;i>=1;i--) rt[i]=modify(rt[i+1],1,n,val[i],1);
	while(q--)
	{
		int l,r,k;
		cin>>l>>r>>k;
		if(r-l+1<k) cout<<-1<<endl;
		else cout<<a[query(rt[l],rt[r+1],k,1,n)].s<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值