题解 可怜的狗狗

P1533 可怜的狗狗

更好阅读体验

题意:

小卡家有N只狗,由于品种、年龄不同,每一只狗都有一个不同的漂亮值;
漂亮值与漂亮的程度成反比(漂亮值越低越漂亮),吃饭时,狗狗们会
按顺序站成一排等着主人给食物。可是嘉嘉真的很懒,他才不肯喂这么多狗呢,
这多浪费时间啊,于是他每次就只给第i只到第j只狗中第k漂亮的狗狗喂食(好
狠心的人啊).而且为了保证某一只狗狗不会被喂太多次,他喂的每个区间(i,j)不互相包含;

思路:因为要找的是排名第k的,考虑主席树和平衡树;

不会平衡树的点这里哦
由于刚学平衡树,这里提供平衡树思路,以为有很多区间,不可能
把上一次全删掉再一个一个加,T飞?
考虑莫队的思想,这题可以用莫队(不过我不会),可以把询问离线,拍下序,每次把
上下两次区间重复的就不用删除了,有大佬直接过了,可我常数大,不过吸个氧跑很快的;

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3e5+7;
struct node{
	int ff,val,siz,cnt,ch[2];
}t[N];
struct quary{
	int l,r,k,id;
	friend bool operator <(const quary &x,const quary &y){
		return x.r<y.r;
	}
}q[N<<1];
int n,m,tot,root;
int a[N],ans[N];

void up(int x){
	t[x].siz=t[x].cnt+t[t[x].ch[0]].siz+t[t[x].ch[1]].siz;
} 

void rotate(int x){
	int y=t[x].ff;
	int z=t[y].ff;
	int k=t[y].ch[1]==x;
	t[z].ch[t[z].ch[1]==y]=x;
	t[x].ff=z;
	t[y].ch[k]=t[x].ch[k^1];
	t[t[x].ch[k^1]].ff=y;
	t[x].ch[k^1]=y;
	t[y].ff=x;
	up(y);up(x);
}

void splay(int x,int goal){
	while(t[x].ff!=goal){
		int y=t[x].ff,z=t[y].ff;
		if(z!=goal) (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
		rotate(x);
	}
	if(goal==0) root=x;
}

void insert(int x){
	int u=root,ff=0;
	while(u&&t[u].val!=x){
		ff=u;
		u=t[u].ch[x>t[u].val];
	}
	if(u) t[u].cnt++;
	else{
		u=++tot;
		if(ff) t[ff].ch[x>t[ff].val]=u;
		t[u].siz=t[u].cnt=1;
		t[u].ff=ff;
		t[u].val=x;
	}
	splay(u,0);
}

void find(int x){
	int u=root;
	if(!u) return;
	while(t[u].ch[x>t[u].val]&&t[u].val!=x){
		u=t[u].ch[x>t[u].val];
	}
	splay(u,0);
}

int Nxt(int x,int f){
	find(x);
	int u=root;
	if(x<t[u].val&&f) return u;
	if(x>t[u].val&&!f) return u;
	u=t[u].ch[f];
	while(t[u].ch[f^1]) u=t[u].ch[f^1];
	return u; 
}

void Del(int x){
	int last=Nxt(x,0);
	int nxt=Nxt(x,1);
	splay(last,0);
	splay(nxt,last);
	int del=t[nxt].ch[0];
	if(t[del].cnt>1){
		t[del].cnt--;
		splay(del,0);
	}else t[nxt].ch[0]=0,t[nxt].siz--,t[last].siz--;
}

int k_th(int x){
	int u=root;
	if(t[u].siz<x) return 0;
	while(1){
		int y=t[u].ch[0];
		if(t[y].siz+t[u].cnt<x){
			x-=t[y].siz+t[u].cnt;
			u=t[u].ch[1];
		}else{
			if(x<=t[y].siz) u=y;
			else return t[u].val;
		}
	}
}

int main(){
	insert(-2147483647);
	insert(2147483647);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
		q[i].id=i;
	}
	sort(q+1,q+m+1);
	int x=q[1].l,y=q[1].r;
	for(int i=q[1].l;i<=q[1].r;i++) insert(a[i]);
	ans[q[1].id]=k_th(q[1].k+1);
	for(int i=2;i<=m;i++){
		while(x<q[i].l) Del(a[x]),x++;
		while(y>q[i].r) Del[a[y]],y--;
		while(x>q[i].l) x--,insert(a[x]);
		while(y<q[i].r) y++,insert(a[y]);
//		cout<<x<<" "<<y<<" "<<q[i].k<<"
";
		ans[q[i].id]=k_th(q[i].k+1);
	}
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<"
";
	}
}
原文地址:https://www.cnblogs.com/Aswert/p/13619730.html