1. 程式人生 > 其它 >P2286寵物收養所(Splay)

P2286寵物收養所(Splay)

傳送門:寵物收養所
可以考慮只維護一棵 Splay,隨時判斷寵物和領養者誰多,把多的插入到 Splay 裡,類似營業額統計,對於新加進來的少的求前驅後繼並比較誰更近。(注意判斷相等的特殊情況,處理按題面來)
然後累計到答案裡就可以啦。(reliese 操作刪除的是某個值而不是節點編號,只有我這個蒟蒻才會錯啦)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 80000 + 10;
const int mod = 1000000;
int n,res,tot,root;
int pet,cus;
int opt[N],spe[N],val[N],fa[N],siz[N],cnt[N],ch[N][2];
int create(int v,int fs)
{
	val[++tot] = v,fa[tot] = fs;
	ch[tot][0] = ch[tot][1] = 0;
	siz[tot] = cnt[tot] = 1;
	return tot;
}
void maintain(int x)
{
	if(not x) return;
	siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
}
int getwhich(int x)
{
	return x == ch[fa[x]][1];
}
void rotate(int x)
{
	int ff = fa[x],gf = fa[ff];
	int k = getwhich(x),tmp = ch[x][k^1];
	fa[tmp] = ff,ch[ff][k] = tmp;
	fa[x] = gf;
	if(gf) ch[gf][getwhich(ff)] = x;
	fa[ff] = x,ch[x][k^1] = ff;
	maintain(x),maintain(ff);
}
void splay(int x)
{
	for(int ff = fa[x];ff = fa[x];rotate(x)) 
	    if(fa[ff]) rotate(getwhich(ff) == getwhich(x) ? ff : x);
	root = x;
}
void ins(int v)
{
	if(not root)
	{
		root = create(v,0);
		return ;
	}
	int cur = root,ff = 0;
	while(1)
	{
		if(val[cur] == v)
		{
			cnt[cur]++;
			maintain(cur),maintain(ff);
			splay(cur); break;
		}
		ff = cur;
		cur = ch[cur][val[cur] < v];
		if(not cur)
		{
			ch[ff][val[ff] < v] = create(v,ff);
			maintain(ff);
			splay(tot); break;
		}
	}
}
int bargain(int k)
{
	int cur = root;
	while(1)
	{
		if(k <= siz[ch[cur][0]]) cur = ch[cur][0];
		else if(siz[ch[cur][0]] + cnt[cur] >= k) return val[cur];
		else
		{
			k -= siz[ch[cur][0]] + cnt[cur]; 
			cur = ch[cur][1];
		} 
	}
}
int rankle(int v)
{
	int cur = root,ans = 0;
	while(1)
	{
		if(not cur) return ans + 1;
		if(v < val[cur]) cur = ch[cur][0];
		else if(v == val[cur])
		{
			ans += siz[ch[cur][0]];
			splay(cur);
			return ans + 1;
		}
		else 
		{
			ans += siz[ch[cur][0]] + cnt[cur];
			cur = ch[cur][1];
		}
	}
}
int charge()
{
	int cur = ch[root][0];
	while(ch[cur][1]) cur = ch[cur][1];
	return cur;
}
int recoil()
{
	int cur = ch[root][1];
	while(ch[cur][0]) cur = ch[cur][0];
	return cur;
}
void reliese(int v)
{
	rankle(v);
	if(cnt[root] > 1)
	{
		cnt[root]--; maintain(root);
		return ;
	}
	else if(not ch[root][0] and not ch[root][1])
	{
		root = 0;
		return ;
	}
	else if(not ch[root][0])
	{
		root = ch[root][1];
		fa[root] = 0;
		return ;
	}
	else if(not ch[root][1])
	{
		root = ch[root][0];
		fa[root] = 0;
		return ;
	}
	int tmp = ch[root][1],pre = charge();
	splay(pre);
	fa[tmp] = root;
	ch[root][1] = tmp;
	maintain(root);
}
signed main()
{
	scanf("%lld",&n);
	for(int i = 1;i <= n;i++)
		scanf("%lld%lld",&opt[i],&spe[i]);
	for(int i = 1;i <= n;i++)
	{
		if(pet == cus) ins(spe[i]);
		else if(pet < cus)
		{
			if(opt[i]) ins(spe[i]);
			else
			{
				ins(spe[i]);
				rankle(spe[i]);
				int pre = charge(),suf = recoil();
				if(not pre)
				{
					res = (res + labs(spe[i] - val[suf])) % mod;
					reliese(val[suf]);
				}
				else if(not suf)
				{
					res += labs(spe[i] - val[pre]);
					res %= 1000000;
					reliese(val[pre]);
				}
				else
				{
					if(labs(spe[i] - val[pre]) <= labs(spe[i] - val[suf])) res += labs(spe[i] - val[pre]),res %= 1000000,reliese(val[pre]);
					else res += labs(spe[i] - val[suf]), res %= 1000000,reliese(val[suf]);
				}
				reliese(spe[i]);
			}
		}
		else 
		{
			if(not opt[i]) ins(spe[i]);
			else
			{
				ins(spe[i]);
				rankle(spe[i]);
				int pre = charge(),suf = recoil();
				if(not pre)
				{
					res += labs(spe[i] - val[suf]);
					res %= 1000000;
					reliese(val[suf]);
				}
				else if(not suf)
				{
					res += labs(spe[i] - val[pre]);
					res %= 1000000;
					reliese(val[pre]);
				}
				else
				{
					if(labs(spe[i] - val[pre]) <= labs(spe[i] - val[suf])) res += labs(spe[i] - val[pre]),res %= 1000000,reliese(val[pre]);
					else res += labs(spe[i] - val[suf]), res %= 1000000,reliese(val[suf]);
				}
				reliese(spe[i]);
			}
		}
		opt[i] ? cus++ : pet++;
		//cout << res << endl;
	}
	printf("%lld\n",res);
	return 0;
}