[LOJ557] 你这衣服租来的吗

前言

暴力能搞到rk1,为什么要平衡树呢?

update 2021.7.13 现在是rk3。

题目

LOJ

VJudge

讲解

珂朵莉树做法。如果你还不会,左转模板讲解

当然只有珂朵莉树的话你会在第 (56) 组数据 ( t TLE) ,不过我们合理利用数据的可观测性,发现输出绝大部分都是 (0),于是猜测它询问的区间很大,修改少,但是其实这个数字根本没有这么多。

所以我们只需要记录一下每个数出现次数,在询问之前判断一下整个序列是否有这么多个数字即可过掉这道题。

代码

//12252024832524
#include <set>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define TT template<typename T>
#define IT set<node>::iterator
using namespace std; 

typedef long long LL;
const int MAXN = 100005;
int n,m,lst;
char opt[2];
struct node
{
	int l,r;
	mutable int val;	
	node(int l1,int r1 = -1,int val1 = 0){
		l = l1;
		r = r1;
		val = val1;
	}
	bool operator < (const node &px)const {
		return l < px.l;
	}
};
set<node> s;
unordered_map<int,LL> M;

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

IT split(int pos)
{
	IT it = s.lower_bound(node(pos));
	if(it != s.end() && it->l == pos) return it;
	--it;
	int l = it->l,r = it->r;
	LL dz = it->val;
	s.erase(it);
	s.insert(node(l,pos-1,dz));
	return s.insert(node(pos,r,dz)).first;
}
void merg(int l,int r,int val)
{
	M[val] += r-l+1;
	IT R = split(r+1),L = split(l);
	for(;L != R;++ L) 
	{
		M[L->val] -= (L->r) - (L->l) + 1;
	}
	R = split(r+1),L = split(l);
	s.erase(L,R);
	s.insert(node(l,r,val));
} 
int Query(int l,int r,int k,int v)
{
	IT R = split(r+1),L = split(l);
	for(;L != R;++ L)
		if(L -> val == v)
		{
			int ll = L->l,rr = L->r;
			if(rr-ll+1 < k) k -= rr-ll+1;
			else return ll + k - 1;
		}
	return 0;
}

int main()
{
//	freopen("gold56.in","r",stdin);
//	freopen("mine.out","w",stdout);
	n = Read(); m = Read();
	lst = Read();
	int l = 1,r;
	for(int i = 2;i <= n;++ i) 
	{
		int val = Read();
		if(val != lst) s.insert(node(l,i-1,lst)),M[lst] += i - l,lst = val,l = i;
	}
	s.insert(node(l,n,lst)); M[lst] += n - l + 1; lst = 0;
	while(m --> 0) 
	{
		scanf("%s",opt); l = Read() ^ lst; r = Read() ^ lst;
		if(!l) l = 1;
		if(opt[0] == 'M') merg(l,r,Read() ^ lst);
		else
		{
			int k = Read() ^ lst,v = Read() ^ lst;
			if(M[v] < k) Put(lst = 0,'
');
			else Put(lst = Query(l,r,k,v),'
');
		}
	}
	return 0;
}

后记

这道题数据应该是比较随机的,不然肯定过不了。

原文地址:https://www.cnblogs.com/PPLPPL/p/14592948.html