LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
解题思路
树上带修莫队,搞了两天。。终于开O2+卡常大法贴边过了。。。bzoj上跑了183s。。其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点且两个点的LCA是这两个点的一个,那么树上的路径其实就是in[x]到in[y]。如果不是的话就是out[x]到in[y],且要加上lca,但这样太难统计,所以其实可以变成in[x]到in[y],然后直接特判。假如一段序列中既有一个点的in,又有一个点的out,那么其实就相当于没算,所以要记个vis数组表示这个东西该加还是该减,细节超级超级超级多。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<map> using namespace std;
const int MAXN = ;
typedef long long LL; inline int rd(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?:;ch=getchar();}
while(isdigit(ch)) {x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
} inline void write(LL x){
if(x>) write(x/);
putchar(x%+'');
} int n,m,Q,v[MAXN],w[MAXN],tot,head[MAXN],bl[MAXN],Qnum;
int to[MAXN<<],nxt[MAXN<<],candy[MAXN],sizz,Qcnt,Ccnt;
int in[MAXN],out[MAXN],node[MAXN<<],num,cnt[MAXN];
int fa[MAXN],son[MAXN],siz[MAXN],dep[MAXN],top[MAXN];
LL ans[MAXN],Ans;
bool vis[MAXN];
map<pair<int,int>,int> mp; struct Data{
int l,r,id,pre,lca;
}q[MAXN]; struct Change{
int pos,val;
}c[MAXN]; inline void add(int bg,int ed){
to[++tot]=ed,nxt[tot]=head[bg],head[bg]=tot;
} void dfs1(int x,int f,int d){
fa[x]=f,dep[x]=d,siz[x]=;
in[x]=++num,node[num]=x;
register int maxson=-,u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i];if(u==f) continue;
dfs1(u,x,d+);
siz[x]+=siz[u];
if(siz[u]>maxson) {maxson=siz[u];son[x]=u;}
}
out[x]=++num,node[num]=x;
} void dfs2(int x,int topf){
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);register int u;
for(register int i=head[x];i;i=nxt[i]){
u=to[i];if(u==son[x] || u==fa[x]) continue;
dfs2(u,u);
}
} inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]>dep[y]?y:x;
} inline bool cmp(Data A,Data B){
if(bl[A.l]!=bl[B.l]) return bl[A.l]<bl[B.l];
if(bl[A.r]!=bl[B.r]) return bl[A.r]<bl[B.r];
return A.pre<B.pre;
} inline void Add(int x){
if(!vis[node[x]]){
vis[node[x]]^=;
cnt[candy[node[x]]]++;
Ans+=(LL)w[cnt[candy[node[x]]]]*v[candy[node[x]]];
// cout<<Ans<<endl;
}
else {
vis[node[x]]^=;
Ans-=(LL)w[cnt[candy[node[x]]]]*v[candy[node[x]]];
cnt[candy[node[x]]]--;
}
} inline void Work(int x){
if(vis[node[c[x].pos]]) {
Ans-=(LL)w[cnt[candy[node[c[x].pos]]]]*v[candy[node[c[x].pos]]];
cnt[candy[node[c[x].pos]]]--;cnt[c[x].val]++;
Ans+=(LL)w[cnt[c[x].val]]*v[c[x].val];
}
swap(c[x].val,candy[node[c[x].pos]]);
} int main(){
n=rd(),m=rd(),Q=rd();
for(register int i=;i<=m;i++) v[i]=rd();
for(register int i=;i<=n;i++) w[i]=rd();
register int x,y,opt;
for(register int i=;i<n;i++){
x=rd(),y=rd();
add(x,y),add(y,x);
}
for(register int i=;i<=n;i++) candy[i]=rd();
dfs1(,,);dfs2(,);register int Lca;
for(register int i=;i<=Q;i++){
opt=rd(),x=rd(),y=rd();
if(opt==){
if(mp.count(make_pair(x,y))) Lca=mp[make_pair(x,y)];
else {Lca=LCA(x,y);mp[make_pair(x,y)]=mp[make_pair(y,x)]=Lca;}
if(in[x]>in[y]) swap(x,y);
q[++Qcnt].l=in[x],q[Qcnt].r=in[y],q[Qcnt].id=Qcnt,q[Qcnt].pre=Ccnt,q[Qcnt].lca=in[Lca];
}
else {c[++Ccnt].pos=in[x];c[Ccnt].val=y;}
}
sizz=pow(n,Ccnt?0.6:0.5);
for(register int i=;i<=n;i++) bl[i]=i/sizz+;
// for(int i=1;i<=Qcnt;i++) cout<<q[i].l<<" "<<q[i].r<<endl;
sort(q+,q++Qcnt,cmp);
// for(int i=1;i<=Qcnt;i++) cout<<q[i].l<<" "<<q[i].r<<" "<<q[i].id<<endl;
register int L=q[].l,R=q[].l-,now=;
for(register int i=;i<=Qcnt;i++){
while(L<q[i].l) {Add(L);L++;}
while(L>q[i].l) {L--;Add(L);}
while(R<q[i].r) {R++;Add(R);}
while(R>q[i].r) {Add(R);R--;}
while(now<q[i].pre) {now++;Work(now);}
while(now>q[i].pre) {Work(now);now--;}
if(q[i].lca!=q[i].l) Add(q[i].l);
if(q[i].lca!=q[i].l && q[i].lca!=q[i].r) Add(q[i].lca);
ans[q[i].id]=Ans;
if(q[i].lca!=q[i].l) Add(q[i].l);
if(q[i].lca!=q[i].l && q[i].lca!=q[i].r) Add(q[i].lca);
}
for(register int i=;i<=Qcnt;i++) write(ans[i]),puts("");
return ;
} /*
4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2 0 2 1
1 1 2
1 4 2
*/
LUOGU P4074 [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] ...
- [WC2013][luogu4074] 糖果公园 [树上带修改莫队]
题面: 传送门 思路: 一道实现起来细节比较恶心的题目 但是其实就是一个裸的树上带修改莫队 好像树上莫队也出不了什么结合题目,不像序列莫队天天结合AC自动机.后缀数组...... 莫队学习请戳这里:莫 ...
- BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
- 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, ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- BZOJ 3052 树上带修莫队
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
- P4074 [WC2013]糖果公园 树上莫队带修改
题目链接 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 nn 个游览点构 ...
随机推荐
- day25 模块,sys, logging, json, pickle
Python之路,Day13 = Python基础13 sys模块 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sy ...
- LUOGU P1084 疫情控制(二分+贪心+树上倍增)
传送门 解题思路 比较神的一道题.首先发现是最小值问题,并且具有单调性,所以要考虑二分答案.其次有一个性质是军队越靠上越优,所以我们要将所有的军队尽量向上提,这一过程我们用倍增实现.发现这时有两种军队 ...
- Linux下编译VLC for Android源代码总结
转:http://blog.chinaunix.net/uid-26611383-id-3678766.html 由于项目需要,需要一个在android平台能够支持RTSP协议的播放器,由于之前没有a ...
- js文件操作之——导出Excel (js-xlsx)
前阵子跟server同学讨论一个Excel导出的需求,我说JS搞不定,需要server来做,被server同学强行打脸. 今天研究了下,尼玛,不光可以,还很强大了! 总结:经验是害人的,尤其是在发展迅 ...
- tomcat mysql 练习
[root@k8s-master tomcat_demo]# cat mysql-rc.yml apiVersion: v1 kind: ReplicationController metadata: ...
- Linux权限命令chmod
一.Linux chmod命令修改文件和文件目录权限(默认情况下只有root用户才能使用).命令格式:chmod+修改内容+要修改的文件或者 目录 或者 chmod -R 修改内容 要修改的文件或者 ...
- jQuery链式编程时修复断开的链
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 一次bug死磕经历之Hbase堆内存小导致regionserver频繁挂掉
环境如下: Centos6.5 Apache Hadoop2.7.1 Apache Hbase0.98.12 Apache Zookeeper3.4.6 JDK1.7 Ant1.9.5 Maven3. ...
- Codeforces Round #478 Div2 975A 975B 975C 975D
A. Aramic script 题目大意: 对于每个单词,定义一种集合,这个集合包含且仅包含单词中出现的字母.给你一堆单词,问有多少种这种集合. 题解: 状压,插入set,取size #in ...
- Vim操作 -- 多段复位粘贴
Vim可以多段复制.粘贴.即,内容X复制到寄存器“1”,内容Y复制到寄存器“2”:粘贴时可以选择从“1”还是“2”粘贴. (1) Vim有13个粘贴板,分别是0.1.2.....9.a.“.+:用:r ...