#树上带修莫队,树链剖分#洛谷 4074 [WC2013]糖果公园
分析
考虑将树转换成序列求解,那就用欧拉序,入栈一次出栈一次正好抵消掉
注意当起点不是LCA的时候要将起点加入,剩下就是带修莫队板子题了
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#define rr register
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
using namespace std;
char buf[1<<21],puf[1<<21],*p1,*p2; int nowp=-1;
const int N=100011; typedef long long lll; struct rec{int x,y;}cha[N];
struct node{int y,next;}e[N<<1]; struct four{int l,r,now,rk;}q[N];
int dep[N],c[N],dfn[N],nfd[N<<1],Top[N],Q; lll w[N],now,ans[N]; bool v[N];
int siz[N],fat[N],big[N],n,Cnt[N],col[N],et=1,as[N],tot,bl,NOW,QQ,m,kuai[N<<1];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Flush(){fwrite(puf,1,nowp+1,stdout),nowp=-1;}
inline void Putchar(char x){
if (nowp==(1<<21)) Flush();
puf[++nowp]=x;
}
inline void print(lll ans){
rr char dig[21]; rr int len=-1;
if (ans<0) Putchar('-'),ans=-ans;
do{
dig[++len]=ans%10+48,ans/=10;
}while (ans);
while (len>=0) Putchar(dig[len--]);
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,siz[x]=1;
for (rr int i=as[x],SIZ=-1;i;i=e[i].next)
if (e[i].y!=fa){
dfs1(e[i].y,x),siz[x]+=siz[e[i].y];
if (siz[e[i].y]>SIZ) big[x]=e[i].y,SIZ=siz[e[i].y];
}
}
inline void dfs2(int x,int linp){
nfd[dfn[x]=++tot]=x,Top[x]=linp;
if (big[x]) dfs2(big[x],linp);
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x])
dfs2(e[i].y,e[i].y);
nfd[++tot]=x;
}
inline signed Lca(int x,int y){
while (Top[x]!=Top[y]){
if (dep[Top[x]]<dep[Top[y]]) x^=y,y^=x,x^=y;
x=fat[Top[x]];
}
if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
return x;
}
bool cmp(four a,four b){
if (kuai[a.l]^kuai[b.l]) return a.l<b.l;
if (kuai[a.r]^kuai[b.r]) return kuai[a.l]&1?a.r<b.r:a.r>b.r;
return (kuai[a.l]^kuai[a.r])&1?a.now<b.now:a.now>b.now;
}
inline void doit(int x){
v[x]^=1;
if (v[x]) now+=w[++Cnt[col[x]]]*c[col[x]];
else now-=w[Cnt[col[x]]--]*c[col[x]];
}
inline void update(int Now){
rr int x=cha[Now].x,Y=cha[Now].y,X=col[x];
if (v[x]) now+=w[++Cnt[Y]]*c[Y]-w[Cnt[X]--]*c[X];
col[x]=Y,cha[Now].y=X;
}
signed main(){
n=iut(),m=iut(),QQ=iut();
for (rr int i=1;i<=m;++i) c[i]=iut();
for (rr int i=1;i<=n;++i) w[i]=iut();
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
for (rr int i=1;i<=n;++i) col[i]=iut();
dfs1(1,0),dfs2(1,1);
for (;QQ;--QQ){
rr int typ=iut(),x=iut(),y=iut();
if (typ){
if (dfn[x]>dfn[y]) x^=y,y^=x,x^=y;
q[++Q]=(four){dfn[x],dfn[y],NOW,Q};
}else cha[++NOW]=(rec){x,y};
}
bl=pow(n,NOW?2.0/3:1.0/2);
for (rr int i=1;i<=n*2;++i) kuai[i]=i/bl;
rr int x,y,l,r,Z=0,z; sort(q+1,q+1+Q,cmp);
for (rr int i=1,L=q[1].l,R=L-1;i<=Q;++i){
x=nfd[l=q[i].l],y=nfd[r=q[i].r],z=q[i].now;
while (L>l) doit(nfd[--L]);
while (L<l) doit(nfd[L++]);
while (R>r) doit(nfd[R--]);
while (R<r) doit(nfd[++R]);
while (Z>z) update(Z--);
while (Z<z) update(++Z);
rr int lca=Lca(x,y);
if (x^lca) doit(x),doit(lca);
ans[q[i].rk]=now;
if (x^lca) doit(x),doit(lca);
}
for (rr int i=1;i<=Q;++i) print(ans[i]),Putchar(10);
Flush();
return 0;
}
#树上带修莫队,树链剖分#洛谷 4074 [WC2013]糖果公园的更多相关文章
- luogu4074 [WC2013]糖果公园(树上带修莫队)
link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...
- 【BZOJ-3052】糖果公园 树上带修莫队算法
3052: [wc2013]糖果公园 Time Limit: 200 Sec Memory Limit: 512 MBSubmit: 883 Solved: 419[Submit][Status] ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- BZOJ3052: [wc2013]糖果公园【树上带修莫队】
Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...
- BZOJ 4129 Haruna’s Breakfast ( 树上带修莫队 )
题面 求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述 分析 树上带修莫队板题,问题是怎么求最小的没出现过的权值. 因为只有nnn个点,所以没出现过的最小值一定在[0,n][0,n][0, ...
- BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
- LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
- BZOJ 3052 树上带修莫队
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
- 洛谷P4074 [WC2013]糖果公园(莫队)
传送门 总算会树形莫队了…… 上次听说树形莫队是给树分块,实在看不懂.然后用括号序列的方法做总算能弄明白了 先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下 拿 ...
- NOI模拟 颜色 - 带修莫队/树套树
题意: 一个颜色序列,\(a_1, a_2, ...a_i\)表示第i个的颜色,给出每种颜色的美丽度\(w_i\),定义一段颜色的美丽值为该段颜色的美丽值之和(重复的只计算一次),每次都会修改某个位置 ...
随机推荐
- 06-Redis系列之-哨兵(Redis-Sentinel)和集群详解和搭建
主从架构高可用 主从架构存在的问题 主从复制,主节点发生故障,需要做故障转移.(可以手动转移:让其中一个slave变成master) 主从复制,只有主写数据,所以写能力和存储能力有限 总结:redis ...
- 【ACM专项练习#03】打印图形、栈的合法性、链表操作、dp实例
运营商活动 题目描述 小明每天的话费是1元,运营商做活动,手机每充值K元就可以获赠1元,一开始小明充值M元,问最多可以用多少天? 注意赠送的话费也可以参与到奖励规则中 输入 输入包括多个测试实例.每个 ...
- [Rust] 命名习惯
[Rust] 命名习惯 通用习惯 CamelCase: 首位是大写字母的单词,没有分隔符: snake_case: 使用下划线作为分隔符,小写单词: SCREAMING_SNAKE_CASE: 使用下 ...
- 【Azure Redis Cache】对StackExchange.Redis IOCP错误消息的解读
问题描述 在使用StackExchange.Redis连接到Azure Redis服务时,时常出现StackExchange.Redis.RedisTimeoutException异常. 全部错误消息 ...
- Linux安装Docker教程
介绍 Docker利用Linux核心中的资源分脱机制,例如cgroups,以及Linux核心名字空间(name space),来创建独立的软件容器(containers).可以在单一Linux实体下运 ...
- STL-bitset模拟实现
#include<time.h> #include<string> #include<vector> #include<iostream> using ...
- 一文讲明白Java中线程与进程、并发与与并行、同步与异步
写在开头 ok,everybody,在过去的两周内,我们大体上讲完了Java的集合,在最后我们探讨了关于HashMap线程不安全的原因,又提出了ConcurrentHashMap这个线程安全的集合解决 ...
- MapStruct的一些常规用法
每天坚持写一篇原创文章. 使用过MapStruct之后,再也没用过BeanCopy来复制对象了.确实是非常好用的工具库. MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处 ...
- multiple definition of `MainWindow::MainWindow(QWidget*)
qt刚建好工程运行的时候没问题,后面写了一点东西之后,再运行就发现出现MainWindow重复,我不理解. 解决方法:删除重复的引用. 再重新构建一下就好了.
- MySQL面经总结
MySQL日志 MySQL日志系统 MySQL查询 菜鸟教程SQL内连接 exist和in区别 sql语句优化 MySQL索引 覆盖索引 索引类型:主键索引,二级索引(辅助索引):唯一索引,普通索引, ...