[LUOGU 可怜的狗狗] 主席树 单点修改+区间查询

题目:

题目链接:LUOGU 可怜的狗狗
题解:
学主席树安利的博客:传送门
这个题啊,真的是,,,一个完全可以用莫队写的题,我偏偏写了主席树,,唉,还不是被怼只会写莫队分块,,, 就好好学了主席树,但是,主席树,尽管是名义上的可持久化线段树,但是它的代码和线段树一比就知道还是主席树代码短,主要是因为看它是可持久化的只需要对于把几棵树串起来来回修改就好,线段树还是要遍历整颗树,,,
这个题就是主席树的模板,直接套上就好,离散化好像是之前的一道题的,这道题好像不需要,自动忽略就好。。。。

代码:

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
inline int read()
{
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch<='9'&&ch>='0')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
const int sea=4e5+7;
struct hit{int l,r,sum;}t[sea*40];
int n,m,x,y,k,cnt,a[sea],root[sea];//root[]就是第i棵树 
vector<int>v;
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}//离散化
void alter(int l,int r,int x,int y,int pos)
{
	t[++cnt]=t[y],t[cnt].sum++; x=cnt;//连接
	if(l==r) return ;
	int mid=(l+r)>>1; 
	if(mid>=pos) alter(l,mid,t[x].l,t[y].l,pos);
	else alter(mid+1,r,t[x].r,t[y].r,pos); 
}
int ask(int l,int r,int x,int y,int k)
{
	if(l==r) return l;
	int mid=(l+r)>>1;
	int sum=t[t[y].l].sum-t[t[x].l].sum; 
	if(sum>=k) return ask(l,mid,t[x].l,t[y].l,k);
	else return ask(mid+1,r,t[x].r,t[y].r,k-sum);
}
int main()
{
	n=read(), m=read(); 
	for(int i=1;i<=n;i++) a[i]=read(),v.push_back(a[i]);
	sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
	for(int i=1;i<=n;i++) alter(1,n,root[i],root[i-1],getid(a[i]));
	for(int i=1;i<=m;i++)
	{
		x=read(); y=read(); k=read();
		printf("%d\n",v[ask(1,n,root[x-1],root[y],k)-1]);
	}
	return 0;
}

再放一道主席树的板子题:P3834 【模板】可持久化线段树 1(主席树)
(一定会补代码的,,,,,)

Continue……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值