http://www.lydsy.com/JudgeOnline/problem.php?id=3052

题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]},可以单点修改颜色。(n, m, q<=100000)

#include <bits/stdc++.h>
using namespace std;
const int N=100005, M=100005;
typedef long long ll;
inline int getint() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') (x*=10)+=c-'0', c=getchar(); return x; }
inline void print(ll a) { if(!a) return; print(a/10); putchar('0'+(a%10));}
int ihead[N], cnt, blo[N<<1], f[N][17], FF[N], LL[N], tot, dep[N], cal[N], pos[N<<1], col[M], n, m, W[N], V[M], qu, n_ask, n_tm, col_pre[N];
ll Ans[M], ans;
bool st[N];
struct E { int next, to; }e[N<<1];
struct Q { int x, y, lca, id, tm; }q[M];
struct T { int x, y, last; }Time[M];
inline bool cmp(const Q &a, const Q &b) { return blo[a.x]==blo[b.x]?(blo[a.y]==blo[b.y]?a.tm<b.tm:blo[a.y]<blo[b.y]):blo[a.x]<blo[b.x]; }
inline void add(int x, int y) { e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt; e[++cnt]=(E){ihead[y], x}; ihead[y]=cnt; }
void dfs(int x) {
pos[FF[x]=++tot]=x;
for(int i=1; i<=16; ++i) f[x][i]=f[f[x][i-1]][i-1];
for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=f[x][0])
dep[e[i].to]=dep[x]+1, f[e[i].to][0]=x, dfs(e[i].to);
pos[LL[x]=++tot]=x;
}
inline int LCA(int x, int y) {
if(dep[x]<dep[y]) swap(x, y);
int d=dep[x]-dep[y];
for(int i=16; i>=0; --i) if((d>>i)&1) x=f[x][i]; if(x==y) return x;
for(int i=16; i>=0; --i) if(f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
return f[x][0];
}
inline void update(int x) {
if(st[x]) { ans-=(ll)V[col[x]]*W[cal[col[x]]]; --cal[col[x]]; }
else { ++cal[col[x]]; ans+=(ll)V[col[x]]*W[cal[col[x]]]; }
st[x]=!st[x];
}
inline void change(int a, int b) {
if(st[a]) { update(a); col[a]=b; update(a); }
else col[a]=b;
}
inline void timechange(int &now, int goal) {
while(now<goal) ++now, change(Time[now].x, Time[now].y);
while(now>goal) change(Time[now].x, Time[now].last), --now;
}
void work() {
int l=1, r=0, now=0, nl, nr;
sort(q+1, q+1+n_ask, cmp);
for(int i=1; i<=n_ask; ++i) {
nl=q[i].x; nr=q[i].y;
timechange(now, q[i].tm);
while(l<nl) update(pos[l++]);
while(l>nl) update(pos[--l]);
while(r<nr) update(pos[++r]);
while(r>nr) update(pos[r--]);
if(q[i].lca) update(q[i].lca);
Ans[q[i].id]=ans;
if(q[i].lca) update(q[i].lca);
}
while(r>=l) update(pos[r--]);
}
void pre() {
dfs((n+1)>>1);
int nn=n<<1, sq=pow(nn, 2.0/3)*0.5;
for(int i=1; i<=nn; ++i) blo[i]=(i-1)/sq;
for(int i=1; i<=qu; ++i) {
int type=getint(), x=getint(), y=getint();
if(!type) {
++n_tm;
Time[n_tm]=(T){x, y, col_pre[x]}; col_pre[x]=y;
continue;
}
++n_ask;
if(FF[x]>FF[y]) swap(x, y);
int lca=LCA(x, y);
if(lca==x) q[n_ask]=(Q){FF[x], FF[y], 0, n_ask, n_tm};
else q[n_ask]=(Q){LL[x], FF[y], lca, n_ask, n_tm};
}
}
int main() {
n=getint(); m=getint(); qu=getint();
for(int i=1; i<=m; ++i) V[i]=getint();
for(int i=1; i<=n; ++i) W[i]=getint();
for(int i=1; i<n; ++i) {
int x=getint(), y=getint();
add(x, y);
}
for(int i=1; i<=n; ++i) col[i]=col_pre[i]=getint();
pre();
work();
for(int i=1; i<=n_ask; ++i) print(Ans[i]), puts("");
return 0;
}

  

一开始我直接在每个修改之间计算答案= =然后果断T了= =QAQ

膜拜vfk.....

首先分块是三元分块!并且要进行修改的操作以及逆操作(最坏变成O(n)辣= =)

第三元就是询问的时间。

然后写完后发现还是好慢QAQ

因为我把块大小就是分成了O(n^0.5)QAQ

继续膜拜vfk

发现要分块成O(n^(2/3)).....则有O(n^(1/3))个块...然后具体证明请看 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/

艾雨青大神犇教导我们,将树分块!
如前所述的分块方法。当时艾雨青神犇讲题的时候的分块方法没听清 T_T,上面的分块方法是我自己YY出来的。
取B = n ^ (2 / 3),设 nBlo为块的个数,用bloNum[v]来代表v所在块的编号。(block number)
则同一个块内任意两结点的距离为O(n ^ (2 / 3))的。
按照之前我说的方式对询问进行排序,按顺序作答。
注意到(bloNum[curV], bloNum[curU])一共有nBlo ^ 2个取值。
那么如果移动一次,curV还在原来的块,curU还在原来的块,这种移动的总时间复杂度是O(nBlo ^ 2 * q)的。(因为curTi还要移动)
如果移动一次,curV不在原来的块,curU不在原来的块,这种移动发生的次数最多为 nBlo ^ 2。因为我是排好序的了嘛,相同块的是放在一起的。而这种移动发生一次最坏是O(n + n + q) = O(n)。(n、q是同阶的)
所以这样回答所有询问,时间复杂度就是O(nBlo ^ 2 * n)的。
由于B = n ^ (2 / 3),块的大小介于[B, 3 * B]之间。
则nBlo = O(n ^ (1 / 3))
则时间复杂度为O(n ^ (5 / 3))。

(如果不会dfs序的话请看我上一篇博文【BZOJ】3757: 苹果树

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

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

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

  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. 洛谷 P4074 [WC2013]糖果公园 解题报告

    P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...

  8. AC日记——[WC2013]糖果公园 cogs 1817

    [WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...

  9. COGS1817. [WC2013]糖果公园

    1817. [WC2013]糖果公园 ★★★☆   输入文件:park.in   输出文件:park.out   简单对比时间限制:8 s   内存限制:512 MB [题目描述] Candyland ...

随机推荐

  1. Android屏幕旋转总结

    转自:http://www.myexception.cn/operating-system/1452058.html 1. ProjectConifg.mk中定义宏MTK_LCM_PHYSICAL_R ...

  2. Swipe JS – 移动WEB页面内容触摸滑动类库

    想必做移动前端的同学经常会接到这样子的一个需求,就是在移动设备页面上的banner图能够用手指触摸左右或上下的滑动切换,这在移动设备是个很常见的一个效果,其用户体验远甚于点击一个按钮区域,通过手指的触 ...

  3. [LeetCode] Happy Number

    Happy Number Total Accepted: 35195 Total Submissions: 106936 Difficulty: Easy Write an algorithm to ...

  4. html5 web database

    html5 web database <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  5. Java Thread join() 的用法

    Java Thread中, join() 方法主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码.示例: class ThreadTesterA imple ...

  6. C# Thread 线程状态知识

    .NET 基础类库的System.Threading命名空间提供了大量的类和接口支持多线程.这个命名空间有很多的类.System.Threading.Thread类是创建并控制线程,设置其优先级并获取 ...

  7. hdu 5833 Zhu and 772002 高斯消元

    Zhu and 772002 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test ...

  8. 智能车学习(十六)——CCD学习

    一.使用硬件 1.兰宙CCD四代      优点:可以调节运放来改变放大倍数      缺点:使用软排线(容易坏),CCD容易起灰,需要多次调节   2.野火K60底层     二.CCD硬件电路 ( ...

  9. 【SQL Sever】实现SQL Sever的发布。订阅。 双机热备

    实现SQL Sever的发布和订阅  最大的好处就是: 可以实现读写分离,增删改操作在主数据库服务器上进行,查询在备份数据库服务器上进行.一方面提高软件执行效率,另一方面也减轻主库压力. 本次实现发布 ...

  10. .htaccess是什么?.htaccess几个简单应用

    .htaccess是什么? .htaccess叫分布式配置文件,它提供了针对目录改变配置的方法——在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录.并且子目录中的 ...