1. 程式人生 > 其它 >P2234營業額統計(Splay)

P2234營業額統計(Splay)

傳送門:營業額統計
Splay 練手題,對於營業額維護 Splay。考慮當前節點對於答案的貢獻,直接尋找前驅後繼並判斷誰更近即可,直接累計到答案中。(注意判斷是否存在前驅和後繼)

#include<bits/stdc++.h>
using namespace std;
const int N = 100000 + 10;
const int inf = 1 << 29;
int n,root,res,tot;
int a[N],val[N],fa[N],siz[N],cnt[N],ch[N][2];
int create(int v,int ff)
{
	val[++tot] = v,fa[tot] = ff;
	siz[tot] = cnt[tot] = 1;
	return tot;
}
void maintain(int x)
{
	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(x) == getwhich(ff) ? 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 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 int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
	    scanf("%d",&a[i]);
	res = a[1];
	ins(a[1]);
	for(int i = 2;i <= n;i++)
	{
		ins(a[i]);
		rankle(a[i]); 
		//cout << rankle(a[i]) << endl;
		if(cnt[root] > 1) continue;
		//cout << rankle(a[i]) << endl;
		int mn = inf,mnn = inf;
		//rankle(a[i]);
		if(charge() != 0) mn = val[charge()];
		if(recoil() != 0) mnn = val[recoil()];
		if(charge() != 0 or recoil() != 0) res += min(abs(a[i] - mn),abs(a[i] - mnn));
		//cout << res << endl;
	}
	//cout << cnt[rankle(5)] << endl;
	printf("%d\n",res);
	return 0;
}