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;
}

浙公网安备 33010602011771号