传送门:宠物收养所
可以考虑只维护一棵 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;
}