权值线段树
这题应该是平衡树,然而可以用权值线段树代替
开2棵权值线段树分别表示有哪些权值的人和有哪些权值的宠物
然后查下前驱和后继就好了
/**************************************************************
Problem: 1208
User: syh0313
Language: C++
Result: Accepted
Time:980 ms
Memory:15236 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <map>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
maxn=80010;
const
int
mo=1000000;
int
n,ff[maxn],v[maxn],vv[maxn],linum,topt,root,t;
struct
da{
int
lc,rc,si[2],ma[2],mi[2];}a[maxn*4];
long
long
ans,line[maxn];
map<
int
,
int
>lc;
void
build_tree(
int
&n,
int
l,
int
r)
{
n=++topt;
if
(l==r) {a[n].si[0]=a[n].si[1]=0;
return
;}
int
mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
}
void
updata(
int
n,
int
k)
{
a[n].si[k]=a[lch].si[k]+a[rch].si[k];
a[n].ma[k]=max(a[lch].ma[k],a[rch].ma[k]);
if
(!a[lch].mi[k] && !a[rch].mi[k]) a[n].mi[k]=0;
if
(a[lch].mi[k] && !a[rch].mi[k]) a[n].mi[k]=a[lch].mi[k];
if
(!a[lch].mi[k] && a[rch].mi[k]) a[n].mi[k]=a[rch].mi[k];
if
(a[lch].mi[k] && a[rch].mi[k]) a[n].mi[k]=min(a[lch].mi[k],a[rch].mi[k]);
}
void
tree_add(
int
n,
int
l,
int
r,
int
lc,
int
k,
int
kk)
{
if
(l==r)
{
a[n].si[kk]+=k;
if
(a[n].si[kk]>0) a[n].ma[kk]=a[n].mi[kk]=l;
if
(a[n].si[kk]==0) a[n].ma[kk]=a[n].mi[kk]=0;
return
;
}
int
mid=(l+r)>>1;
if
(lc<=mid) tree_add(lch,l,mid,lc,k,kk);
else
tree_add(rch,mid+1,r,lc,k,kk);
updata(n,kk);
}
int
qpre(
int
n,
int
L,
int
R,
int
l,
int
r,
int
kk)
{
if
(!a[n].si[kk])
return
0;
if
(L==l && R==r)
return
a[n].ma[kk];
int
mid=(L+R)>>1;
if
(r<=mid)
return
qpre(lch,L,mid,l,r,kk);
else
if
(l>=mid+1)
return
qpre(rch,mid+1,R,l,r,kk);
else
return
max(qpre(lch,L,mid,l,mid,kk),qpre(rch,mid+1,R,mid+1,r,kk));
}
int
qnxt(
int
n,
int
L,
int
R,
int
l,
int
r,
int
kk)
{
if
(!a[n].si[kk])
return
0;
if
(L==l && R==r)
return
a[n].mi[kk];
int
mid=(L+R)>>1;
if
(r<=mid)
return
qnxt(lch,L,mid,l,r,kk);
else
if
(l>=mid+1)
return
qnxt(rch,mid+1,R,l,r,kk);
else
{
int
k1=qnxt(lch,L,mid,l,mid,kk),k2=qnxt(rch,mid+1,R,mid+1,r,kk);
if
(!k1 && !k2)
return
0;
if
(k1 && !k2)
return
k1;
if
(!k1 && k2)
return
k2;
return
min(k1,k2);
}
}
int
main()
{
scanf
(
"%d"
,&n);
for
(
int
i=1;i<=n;i++)
scanf
(
"%d%d"
,&ff[i],&v[i]),vv[i]=v[i];
sort(vv+1,vv+n+1);
for
(
int
i=1;i<=n;i++)
if
(!lc[vv[i]]) lc[vv[i]]=++linum,line[linum]=vv[i];
build_tree(root,1,linum);
for
(
int
i=1;i<=n;i++)
{
tree_add(root,1,linum,lc[v[i]],1,ff[i]);
if
(a[root].si[0]>=a[root].si[1])
{
if
(!a[root].si[1])
continue
;
int
k=qpre(root,1,linum,1,linum,1);
int
x1=qpre(root,1,linum,1,k,0),x2=qnxt(root,1,linum,k,linum,0);
if
(x1==0)
{ans+=
abs
(line[k]-line[x2]); tree_add(root,1,linum,x2,-1,0);}
else
if
(x2==0)
{ans+=
abs
(line[k]-line[x1]); tree_add(root,1,linum,x1,-1,0);}
else
{
if
(line[k]-line[x1]<=line[x2]-line[k])
{ans+=
abs
(line[k]-line[x1]); tree_add(root,1,linum,x1,-1,0);}
else
{ans+=
abs
(line[k]-line[x2]); tree_add(root,1,linum,x2,-1,0);}
}
tree_add(root,1,linum,k,-1,1); ans%=mo;
}
else
{
if
(!a[root].si[0])
continue
;
int
k=qpre(root,1,linum,1,linum,0);
int
x1=qpre(root,1,linum,1,k,1),x2=qnxt(root,1,linum,k,linum,1);
if
(x1==0)
{ans+=
abs
(line[k]-line[x2]); tree_add(root,1,linum,x2,-1,1);}
else
if
(x2==0)
{ans+=
abs
(line[k]-line[x1]); tree_add(root,1,linum,x1,-1,1);}
else
{
if
(line[k]-line[x1]<=line[x2]-line[k])
{ans+=
abs
(line[k]-line[x1]); tree_add(root,1,linum,x1,-1,1);}
else
{ans+=
abs
(line[k]-line[x2]); tree_add(root,1,linum,x2,-1,1);}
}
tree_add(root,1,linum,k,-1,0); ans%=mo;
}
}
printf
(
"%lld\n"
,ans);
return
0;
}