好写好调的莫队算法,就算上树了仍然好写好调。

传送门

http://uoj.ac/problem/58

简要做法

将树按照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】糖果公园的更多相关文章

  1. bzoj 3052: [wc2013]糖果公园 带修改莫队

    3052: [wc2013]糖果公园 Time Limit: 250 Sec  Memory Limit: 512 MBSubmit: 506  Solved: 189[Submit][Status] ...

  2. BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)

    题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...

  3. [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

    题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...

  4. BZOJ 3052: [wc2013]糖果公园 | 树上莫队

    题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...

  5. bzoj 3052: [wc2013]糖果公园【树上带修改莫队】

    参考:http://blog.csdn.net/lych_cys/article/details/50845832 把树变成dfs括号序的形式,注意这个是不包含lca的(除非lca是两点中的一个) 然 ...

  6. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  7. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  8. 【BZOJ3052】【UOJ#58】【WC2013】糖果公园(树上莫队)

    [BZOJ3052][UOJ#58][WC2013]糖果公园(树上莫队) 题面 UOJ 洛谷 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引 ...

  9. [BZOJ3052][UOJ#58][WC2013]糖果公园

    [BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...

随机推荐

  1. Linux进入单用户模式(passwd root修改密码)

    进入单用户模式——passwd root修改密码 1.在grub 页面输入a,进入修改内核模式 2.在内核的结尾“/”,输入空格,在输入single,回车 3.启动系统,进入单用户模式 4.Passw ...

  2. 一些兼容性的meta标签

    <!-- 仅针对IOS的Safari顶端状态条的样式(可选default/black/black-translucent )--> <meta name="apple-mo ...

  3. 使用oVal进行Java Bean 验证的注意事项

    如果需要不同条件验证不同的属性的时候,需要使用profiles属性,每个校验注解符中都有.注意:oVal默认是启用所有的profiles,所以在对单独一个profile进行启用的时候,需要先disab ...

  4. castle activerecord 学习过程出现的问题

    优点: 1.CRUD:代码简洁 2.不用配置map 3.自带事务方便 4.自带IOC 5.自带 数据有效性验证 缺点: 1.自增长(Oracle 一直提示序号不存在,有空继续尝试) 2.多条件,直接用 ...

  5. 扔几道sb题

    1.给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间. 你能求 ...

  6. 【Nowcoder】玩游戏

    Portal --> Nowcoder197D Solution 所以说这是一道==纯粹的人类智慧题是这样吗qwq ​ 一开始的时候想sg函数qwq然后发现..好像根本不能拆成独立的子游戏嘛qw ...

  7. C++实现人员信息管理系统模拟

    利用C++语言实现基本的学生信息管理系统: 要求: 1-设置管理员密码 2-人员数据有:姓名,性别等基本的信息 3-可以添加,删除,保存,统计 #include<iostream> #in ...

  8. (转) 使用vivado创建工程 4[完结]

    由于自己手头暂时没有开发板,因此本节没有测试,故告之. Connecting to ZedBoardBefore we can run the application we have to conne ...

  9. ndk如何将代码放在jni之外

    LOCAL_PATH := $(call my-dir)SDK_PATH := ../../.. include $(CLEAR_VARS)LOCAL_MODULE := libiconv_stati ...

  10. sublime wrong

    Q1: sublime报错: There are no packages available for installation A1: window下的:C:\Windows\System32\dri ...