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

题目:

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

代码:

#include
#include
#include
#include
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……

你可能感兴趣的:(刷题)