您的位置:首页 > 其它

uoj#58./bzoj3052 【WC2013】糖果公园 //树上带修改莫队

2018-01-17 22:37 453 查看

uoj#58. 【WC2013】糖果公园

题意

有一棵N(<=1e5)个点的树,每个点对应M(<=1e5)种糖果中的一种。

一条路径的权值定义为∑i(Vi∗∑tij=1Wj),其中i为路径中出现的不同种类糖果,ti为第i种糖果的出现次数,V和W给定。

Q(<=1e5)次操作,每次操作修改一个点对应的糖果种类,或询问路径(u,v)的权值。

题解

半年前写了一半,然而代码弄丢了。

树上莫队和带修改莫队放一起,算是比较模板的题?

跑得太慢了,不好意思写题解,就放个代码吧。

代码

#include<bits/stdc++.h>
#define N 100005
#define L 18
#define Y no[i]
#define X mx[op]
using namespace std;
typedef long long ll;
ll ans
,s,ss
;
bool vis
;
char ch;
inline void rd(int &x)
{
x=0;
do ch=getchar();
while(ch<'0'||ch>'9');
do x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
while(ch>='0'&&ch<='9');
}
int n,m,q,sqr,tp,mx
,my
,pre
,
ql
,qr
,qx
,no
,mt,qt,t
,
V
,W
,c
,b
,f
[L],dep
,
to[N<<1],hd[N<<1],lk
,cnt;
inline void add(int u,int v)
{to[++cnt]=v,hd[cnt]=lk[u],lk[u]=cnt;}
void dfs(int x)
{
dep[x]=dep[f[x][0]]+1;
b[x]=tp++/sqr;
for(int i=1;f[x][i-1];i++)
f[x][i]=f[f[x][i-1]][i-1];
for(int k,i=lk[x];i;i=hd[i])
if(!dep[k=to[i]])
f[k][0]=x,dep[k]=dep[x]+1,dfs(k);
}
bool cmp(int x,int y)
{
return (b[ql[x]]^b[ql[y]])?b[ql[x]]<b[ql[y]]:
((b[qr[x]]^b[qr[y]])?b[qr[x]]<b[qr[y]]:qx[x]<qx[y]);
}
inline void ins(int x,int v)
{
s-=ss[x];
if(v>0)ss[x]+=(ll)V[x]*W[t[x]+1];
else ss[x]-=(ll)V[x]*W[t[x]];
t[x]+=v,s+=ss[x];
}
inline void mdf(int x)
{ins(c[x],(vis[x]^=1)?1:-1);}
inline void trans(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y])
mdf(x),x=f[x][0];
while(x^y)mdf(x),mdf(y),x=f[x][0],y=f[y][0];
}
int op,u,v,x,y;
int main()
{
rd(n),rd(m),rd(q);
for(int i=1;i<=m;rd(V[i++]));
for(int i=1;i<=n;rd(W[i++]));
for(int i=1;i<n;i++)
rd(u),rd(v),add(u,v),add(v,u);
for(int i=1;i<=n;rd(c[i++]));
while(sqr*sqr*sqr<n)sqr++;
sqr=n/sqr;
dfs(1),tp=0;
for(int i=1;i<=q;i++)
{
rd(op);
if(op)
{
rd(ql[qt]),rd(qr[qt]);
if(b[ql[qt]]>b[qr[qt]])
swap(ql[qt],qr[qt]);
no[qt]=qt,qx[qt++]=mt;
}
else
rd(u),rd(my[mt]),
pre[mt]=c[mx[mt]=u],
c[u]=my[mt++];
}
sort(no,no+qt,cmp);
u=v=1,op=mt;
for(int i=0;i<qt;i++)
{
trans(u,ql[Y]),u=ql[Y];
trans(v,qr[Y]),v=qr[Y];
while(op<qx[Y])
{
if(vis[X])
ins(c[X],-1),ins(my[op],1);
c[X]=my[op],op++;
}
while(op>qx[Y])
{
op--;
if(vis[X])
ins(c[X],-1),ins(pre[op],1);
c[X]=pre[op];
}
x=u,y=v;
if(dep[y]>dep[x])swap(x,y);
for(int j=L-1;dep[x]^dep[y];j--)
if(dep[f[x][j]]>=dep[y])
x=f[x][j];
for(int j=L-1;j>=0;j--)
if(f[x][j]^f[y][j])
x=f[x][j],y=f[y][j];
if(x^y)x=f[x][0];
mdf(x);ans[Y]=s;mdf(x);
}
for(int i=0;i<qt;i++)
printf("%lld\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: