[WC2013][luogu4074] 糖果公园 [树上带修改莫队]
2024-09-07 01:14:15
题面:
思路:
一道实现起来细节比较恶心的题目
但是其实就是一个裸的树上带修改莫队
好像树上莫队也出不了什么结合题目,不像序列莫队天天结合AC自动机、后缀数组......
莫队学习请戳这里:莫队
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
inline ll read(){
ll re=,flag=;char ch=getchar();
while(ch>''||ch<''){
if(ch=='-') flag=-;
ch=getchar();
}
while(ch>=''&&ch<='') re=(re<<)+(re<<)+ch-'',ch=getchar();
return re*flag;
}
struct edge{
ll to,next;
}a[];
ll n,m,Q,first[],cntt,clk,block;
ll fa[],dep[],st[][],dfn[];
ll v[],w[],x[];
inline void add(ll u,ll v){
a[++cntt]=(edge){v,first[u]};first[u]=cntt;
a[++cntt]=(edge){u,first[v]};first[v]=cntt;
}
void dfs(ll u,ll f){
//cout<<"dfs "<<u<<" "<<f<<"\n";
ll i,v;
fa[u]=st[u][]=f;dep[u]=dep[f]+;dfn[u]=++clk;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(v==f) continue;
dfs(v,u);
}
}
void init(){
for(ll i=;i<=;i++){
for(ll j=;j<=n;j++){
st[j][i]=st[st[j][i-]][i-];
}
}
}
void _swap(ll &l,ll &r){l^=r;r^=l;l^=r;}
ll LCA(ll l,ll r){
//cout<<"lca "<<l<<" "<<r<<"\n";
if(dep[l]>dep[r]) _swap(l,r);
ll i;
for(i=;i>=;i--) if(dep[st[r][i]]>=dep[l]) r=st[r][i];
if(l==r) return l;
for(i=;i>=;i--){
if(st[l][i]!=st[r][i]){
l=st[l][i];r=st[r][i];
}
}
return fa[l];
}
ll curl,curr,curc,cntq,cntc,cnt[];bool vis[];
ll ans[],tot;
struct query{
ll l,r,c,i;
}q[];
bool cmp(query l,query r){
if(dfn[l.l]/block!=dfn[r.l]/block) return dfn[l.l]/block<dfn[r.l]/block;
else{
if(dfn[l.r]/block!=dfn[r.r]/block)
return dfn[l.r]/block<dfn[r.r]/block;
else return l.c<r.c;
}
}
struct change{
ll pos,to;
}c[];
void rev(ll i){
if(vis[i]) vis[i]=,tot-=v[x[i]]*w[cnt[x[i]]],cnt[x[i]]--;
else vis[i]=,cnt[x[i]]++,tot+=v[x[i]]*w[cnt[x[i]]];
//cout<<"rev node "<<i<<" "<<x[i]<<" "<<tot<<"\n";
}
void change(ll i){
//cout<<"change node "<<i<<" "<<c[i].pos<<" "<<c[i].to<<"\n";
if(!vis[c[i].pos]) _swap(c[i].to,x[c[i].pos]);
else{
rev(c[i].pos);
_swap(c[i].to,x[c[i].pos]);
rev(c[i].pos);
}
}
int main(){
memset(first,-,sizeof(first));
ll i,t1,t2,t3;
n=read();m=read();Q=read();block=(ll)pow(n,0.60);
for(i=;i<=m;i++) v[i]=read();
for(i=;i<=n;i++) w[i]=read();
for(i=;i<n;i++){
t1=read();t2=read();add(t1,t2);
}
for(i=;i<=n;i++) x[i]=read();
dfs(,);init();
//for(i=1;i<=n;i++) cout<<fa[i]<<" "<<dep[i]<<"\n";
for(i=;i<=Q;i++){
t1=read();t2=read();t3=read();
if(t1) q[++cntq].l=t2,q[cntq].r=t3,q[cntq].c=cntc,q[cntq].i=cntq;
else c[++cntc].pos=t2,c[cntc].to=t3;
//cout<<"finish read in "<<i<<"\n";
}
sort(q+,q+cntq+,cmp);
//for(i=1;i<=cntq;i++)
//cout<<q[i].l<<" "<<q[i].r<<" "<<q[i].c<<" "<<q[i].i<<"\n"; if(dfn[q[].l]>dfn[q[].r]) _swap(q[].l,q[].r);
ll lca=LCA(q[].l,q[].r),l,r;curl=q[].l;curr=q[].r;
l=curl;r=curr;
while(l!=lca) rev(l),l=fa[l];
while(r!=lca) rev(r),r=fa[r];
while(curc<q[].c) change(++curc);
rev(lca);ans[q[].i]=tot;rev(lca);
for(i=;i<=cntq;i++){
//cout<<"i=="<<i<<"\n";
if(dfn[q[i].l]>dfn[q[i].r]) _swap(q[i].l,q[i].r);
lca=LCA(curr,q[i].r);l=curr;r=q[i].r;
while(l!=lca) rev(l),l=fa[l];
while(r!=lca) rev(r),r=fa[r];
lca=LCA(curl,q[i].l);l=curl;r=q[i].l;
while(l!=lca) rev(l),l=fa[l];
while(r!=lca) rev(r),r=fa[r];
while(curc>q[i].c) change(curc--);
while(curc<q[i].c) change(++curc);
lca=LCA(q[i].l,q[i].r);
rev(lca);ans[q[i].i]=tot;rev(lca);
curl=q[i].l;curr=q[i].r;
}
for(i=;i<=cntq;i++) printf("%lld\n",ans[i]);
}
最新文章
- oracle or语句的坑
- 20169212《Linux内核原理与分析》第五周作业
- mysql 简单优化方法
- Python学习笔记——文件写入和读取
- Mysql数据库操作系统及配置参数优化
- 解决多网卡SNMP获取不到数据的问题
- 最近学习linux常用命令。
- UIWebView stringByEvaluatingJavaScriptFromString的使用方法
- Fragment 和 FragmentActivity的使用(二)
- 制作动态链接库给opencv程序使用(使用QtCreator)
- homework-05 服务器与客户端
- 【SICP读书笔记(四)】练习2.27 --- 表序列reverse的扩展:树结构的deep-reverse
- 团队作业8——Beta 阶段冲刺4th day
- JAVA的helloworld
- 从零开始搭建一个vue.js的脚手架
- linux下查找堆栈信息例子
- C++程序设计方法3:数组下标运算符重载
- C#_02.10_基础一_.NET框架
- Uboot 引导内核时加载地址与入口地址问题
- 利用WCF实现上传下载文件服务