UOJ#58/BZOJ 3052【WC2013】糖果公园
好写好调的莫队算法,就算上树了仍然好写好调。
传送门
简要做法
将树按照dfs序分块,然后将询问按照(u所在块,v所在块,时间)作为关键字进行排序,依次转移。
转移只需依次把u,v移动到目标位置,将经过的点的标记翻转,同时每种颜色统计出现次数。
细节
转移的时候用了一个trick,把点权转换为边权,每个点代表它向父亲的边,于是不用考虑各种边界情况,处理询问的时候再将LCA加上即可。
具体方法:将端点u转移到端点v(此处uv的含义与询问的uv含义不同)时,先将u,v调整到同一深度,然后暴力向上走直到相遇。
其他
按照【王室联邦】的方法分块会更快一些。
具体参见vfk博客:http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
一开始我的分块方法是错的:dfs,依次进栈,size大于块大小时弹栈,这样会导致同一个块中节点分散,于是T到飞起。

(调了好几次参数仍然跑不过同学的代码
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=100005, MAXB=1e7, S=1600;
char BUF[MAXB], *cp=BUF;
void rd(int &x){
x=0;
while(*cp<'0'||'9'<*cp) cp++;
while('0'<=*cp&&*cp<='9') x=x*10+*cp-'0', cp++;
}
int N, M, K, ne, nq, no, top, tot, ord;
int vis[MAXN], V[MAXN], W[MAXN], co[MAXN], n[MAXN], st[MAXN];
int m[MAXN], fa[MAXN], d[MAXN], dfn[MAXN], be[MAXN], lca[MAXN], f[MAXN];
ll sum, ans[MAXN];
vector<P> ql[MAXN];
int find(int x){return x==f[x]?x:(f[x]=find(f[x]));}
void unite(int u, int v){f[find(u)]=find(v);}
struct Edge{Edge *nxt; int to;}E[MAXN<<1],*hd[MAXN];
void adde(int u, int v){
E[ne].to=v;E[ne].nxt=hd[u];hd[u]=&E[ne++];
E[ne].to=u;E[ne].nxt=hd[v];hd[v]=&E[ne++];
}
void addq(int u, int v, int i){ql[u].push_back(P(v,i));ql[v].push_back(P(u,i));}
void dfs(int u, int p){
vis[u]=1; dfn[u]=ord++; fa[u]=p; d[u]=d[p]+1;
for(Edge *e=hd[u]; e; e=e->nxt){
int v=e->to;
if(v!=p){
dfs(v,u); unite(v,u);
}
}
for(int i=0; i<ql[u].size(); ++i)
if(vis[ql[u][i].first]) lca[ql[u][i].second]=find(ql[u][i].first);
}
struct Qry{
int l, r, t, id;
bool operator<(const Qry &o)const{
if(be[l]==be[o.l]) return be[r]==be[o.r]?((be[r]&1)?t>o.t:t<o.t):((be[l]&1)?be[r]>be[o.r]:be[r]<be[o.r]);
return be[l]<be[o.l];
}
}Q[MAXN];
struct Op{int x, y;}O[MAXN];
inline void mdf(int x, int y){
if(co[x]!=y&&m[x]){
sum+=(ll)V[y]*W[n[y]+1]-(ll)V[co[x]]*W[n[co[x]]];
n[y]++; n[co[x]]--; if(n[2]==-1) exit(233);
}
}
inline void flip(int x){
if(!m[x]) m[x]=1, sum+=(ll)V[co[x]]*W[++n[co[x]]];
else m[x]=0, sum-=(ll)V[co[x]]*W[n[co[x]]--];
}
void tr(int u, int v){
while(d[v]>d[u]) flip(v),v=fa[v];
while(d[u]>d[v]) flip(u),u=fa[u];
while(u!=v) flip(v),v=fa[v],flip(u),u=fa[u];
}
int main(){
fread(BUF, 1, MAXB, stdin);
rd(N),rd(M),rd(K);
for(int i=1; i<=M; ++i) rd(V[i]);
for(int i=1; i<=N; ++i) rd(W[i]);
for(int i=1,u,v; i<N; ++i) rd(u),rd(v),adde(u,v);
for(int i=1; i<=N; ++i) rd(co[i]);
for(int i=0,t,x,y; i<K; ++i){
rd(t),rd(x),rd(y);
if(t==1) addq(x,y,nq),Q[nq].l=x,Q[nq].r=y,Q[nq].id=nq,Q[nq].t=no,nq++;
else O[no].x=x,O[no].y=y,no++;
}
for(int i=1; i<=N; ++i) f[i]=i;
dfs(1,0); tot++; while(top) be[st[--top]]=tot;
for(int i=0; i<nq; ++i) if(dfn[Q[i].l]>dfn[Q[i].r]) swap(Q[i].l,Q[i].r);
for(int i=1; i<=N; ++i) be[i]=dfn[i]/S;
sort(Q,Q+nq);
for(int i=0,l=1,r=1,t=0; i<nq; ++i){
tr(l,Q[i].l); l=Q[i].l;
tr(r,Q[i].r); r=Q[i].r;
for(;t<Q[i].t;++t) mdf(O[t].x,O[t].y),swap(co[O[t].x],O[t].y);
for(;t>Q[i].t;)--t,mdf(O[t].x,O[t].y),swap(co[O[t].x],O[t].y);
flip(lca[Q[i].id]); ans[Q[i].id]=sum; flip(lca[Q[i].id]);
}
for(int i=0; i<nq; ++i) printf("%lld\n", ans[i]);
return 0;
}
UOJ#58/BZOJ 3052【WC2013】糖果公园的更多相关文章
- bzoj 3052: [wc2013]糖果公园 带修改莫队
3052: [wc2013]糖果公园 Time Limit: 250 Sec Memory Limit: 512 MBSubmit: 506 Solved: 189[Submit][Status] ...
- BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)
题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...
- [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】
题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...
- BZOJ 3052: [wc2013]糖果公园 | 树上莫队
题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...
- bzoj 3052: [wc2013]糖果公园【树上带修改莫队】
参考:http://blog.csdn.net/lych_cys/article/details/50845832 把树变成dfs括号序的形式,注意这个是不包含lca的(除非lca是两点中的一个) 然 ...
- 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法
[题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...
- 【BZOJ】3052: [wc2013]糖果公园
http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...
- 【BZOJ3052】【UOJ#58】【WC2013】糖果公园(树上莫队)
[BZOJ3052][UOJ#58][WC2013]糖果公园(树上莫队) 题面 UOJ 洛谷 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引 ...
- [BZOJ3052][UOJ#58][WC2013]糖果公园
[BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...
随机推荐
- Guide: Solr performance tuning--转载
原文地址:http://h3x.no/2011/05/10/guide-solr-performance-tuning Introduction I have for the last year be ...
- 【bzoj3992】[SDOI2015]序列统计 原根+NTT
题目描述 求长度为 $n$ 的序列,每个数都是 $|S|$ 中的某一个,所有数的乘积模 $m$ 等于 $x$ 的序列数目模1004535809的值. 输入 一行,四个整数,N.M.x.|S|,其中|S ...
- 《转》理解Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值.定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...
- C++解析(27):数组、智能指针与单例类模板
0.目录 1.数组类模板 1.1 类模板高效率求和 1.2 数组类模板 1.3 堆数组类模板 2.智能指针类模板 2.1 使用智能指针 2.2 智能指针类模板 3.单例类模板 3.1 实现单例模式 3 ...
- 【转】ssh免密码登录的原理
工作第一天,就需要登录各种服务器,免密码登录无疑能大大的提高工作效率.以前只知道配置,今天了解了下原理. 免密码登录原理 图解,server A免登录到server B: 1.在A上生成公钥私钥. 2 ...
- Day21-Cookie
1. Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密).例如在某个网站上保存了用户名和密码,3个月内 ...
- QString::QString 中文乱码
QString::QString 中文乱码 处理方法: 1. QString str = QString::fromLocal8Bit("中文"); // vs2008 vs200 ...
- # HNOI2012 ~ HNOI2018 题解
HNOI2012 题解 [HNOI2012]永无乡 Tag:线段树合并.启发式合并 联通块合并问题. 属于\(easy\)题,直接线段树合并 或 启发式合并即可. [HNOI2012]排队 Tag:组 ...
- 【MVVM Dev】PART_Editor的使用
一.前言 在日常的界面开发中,我们大多使用MVVM模式进行开发.通常情况下,一个PropertyGridControl或者DataGrid的ItemsSource设置好, 然后每一列绑定好 ...
- 洛谷 P2123 皇后游戏 解题报告
P2123 皇后游戏 题意: 给定\(T\)组长为\(n\)的\(A\),\(B\)数组和\(C\)的计算方法,求一种排列方法,使最大的\(C\)最小化. 数据范围: \(1 \le T \le 10 ...