LOJ #2107. 「JLOI2015」城池攻占 Splay+启发式合并
这道题拿左偏树做的话时间复杂度好像是 $O(n \log n)$ 的,拿 $Splay$ 的话就是 $O(n \log^2 n)$ 的.
$Splay$ 真恶心,真心不好写,要不是可以练习代码能力的话我才不用 $Splay$.
code:
#include <bits/stdc++.h>
#define ll long long
#define N 300006
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
using namespace std;
const ll inf=7e18+2;
ll h[N];
struct opt
{
int a;
ll v;
}tree[N];
int DE;
int n,m,edges,tot,FL,Ans1[N],Ans2[N],ge[N];
int dep[N],hd[N],to[N],nex[N],rt[N],ou[N];
namespace BST
{
#define lson s[x].ch[0]
#define rson s[x].ch[1]
struct node
{
ll v,a,b;
int si,ch[2],f,id;
void ini()
{
v=0,a=1,b=0;
si=1,ch[0]=ch[1]=f=id=0;
}
}s[N*20];
int tot;
stack<int>S;
inline int get(int x) { return s[s[x].f].ch[1]==x; }
inline int newnode()
{
if(S.empty())
return ++tot;
else
{
int u=S.top();
S.pop();
return u;
}
}
inline void pushup(int x)
{
s[x].si=s[lson].si+s[rson].si+1;
}
inline void mark_a(int x,ll a)
{
s[x].a*=a,s[x].b*=a;
if(s[x].v!=inf&&s[x].v!=-inf)
s[x].v*=a;
}
inline void mark_b(int x,ll b)
{
s[x].b+=b;
if(s[x].v!=inf&&s[x].v!=-inf)
s[x].v+=b;
}
inline void pushdown(int x)
{
if(s[x].a!=1)
{
if(lson)
mark_a(lson,s[x].a);
if(rson)
mark_a(rson,s[x].a);
s[x].a=1;
}
if(s[x].b)
{
if(lson)
mark_b(lson,s[x].b);
if(rson)
mark_b(rson,s[x].b);
s[x].b=0;
}
}
int ins(int &x,int ff,int id,ll v)
{
if(!x)
{
x=newnode();
s[x].ini();
s[x].f=ff,s[x].id=id,s[x].v=v;
return x;
}
++s[x].si;
pushdown(x);
return ins(s[x].ch[v>s[x].v],x,id,v);
}
inline int find(int x,ll v)
{
int r=0;
while(1)
{
if(!x)
break;
pushdown(x);
if(s[x].v>=v)
r=x,x=lson;
else
x=rson;
}
return r;
}
inline void rotate(int x)
{
int old=s[x].f,fold=s[old].f,which=get(x);
s[old].ch[which]=s[x].ch[which^1];
if(s[old].ch[which])
s[s[old].ch[which]].f=old;
s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;
if(fold)
s[fold].ch[s[fold].ch[1]==old]=x;
pushup(old),pushup(x);
}
void splay(int x,int &tar)
{
int u=s[tar].f;
for(int fa;(fa=s[x].f)!=u;rotate(x))
if(s[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
void ope(int &x,int y)
{
if(s[y].v!=-inf&&s[y].v!=inf)
{
int p=ins(x,0,s[y].id,s[y].v);
if((rand()%3)==0)
splay(p,x);
}
pushdown(y);
if(s[y].ch[0])
ope(x,s[y].ch[0]);
if(s[y].ch[1])
ope(x,s[y].ch[1]);
S.push(y);
}
void del(int x)
{
if(!x)
return;
if(s[x].v!=inf&&s[x].v!=-inf)
{
Ans1[FL]+=1;
ou[s[x].id]=1;
Ans2[s[x].id]+=dep[ge[s[x].id]]-dep[FL];
}
pushdown(x);
if(lson)
del(lson);
if(rson)
del(rson);
S.push(x);
}
#undef lson
#undef rson
};
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void merge(int x,int y)
{
if(BST::s[rt[x]].si<BST::s[rt[y]].si)
swap(rt[x],rt[y]);
BST::ope(rt[x],rt[y]);
}
void dfs(int x,int ff)
{
dep[x]=dep[ff]+1;
BST::ins(rt[x],0,0,inf);
BST::ins(rt[x],0,0,-inf);
for(int i=hd[x];i;i=nex[i])
{
int y=to[i];
dfs(y,x),merge(x,y);
}
FL=x;
int q=BST::find(rt[x],h[x]);
BST::splay(q,rt[x]);
BST::s[BST::s[q].ch[0]].f=0;
BST::del(BST::s[q].ch[0]);
BST::s[q].ch[0]=0;
BST::pushup(q);
if(x!=1)
{
if(tree[x].a==0)
BST::mark_b(q,tree[x].v);
if(tree[x].a==1)
BST::mark_a(q,tree[x].v);
}
}
int main()
{
// setIO("input");
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
scanf("%lld",&h[i]);
for(i=2;i<=n;++i)
scanf("%d%d%lld",&j,&tree[i].a,&tree[i].v),add(j,i);
for(i=1;i<=m;++i)
{
ll v;
int u;
scanf("%lld%d",&v,&u);
ge[i]=u;
BST::ins(rt[u],0,i,v);
}
dfs(1,0);
for(i=1;i<=n;++i)
printf("%d\n",Ans1[i]);
for(i=1;i<=m;++i)
if(!ou[i])
printf("%d\n",dep[ge[i]]);
else
printf("%d\n",Ans2[i]);
return 0;
}

浙公网安备 33010602011771号