【BZOJ】【3757】苹果树

树分块

  orz HZWER

  http://hzwer.com/5259.html

  不知为何我原本写的倍增求LCA给WA了……学习了HZWER的倍增新姿势~

  树上分块的转移看vfk博客的讲解吧……(其实是先指向hzwer博客,再跳转vfk和KoribohG……)

  vfk讲的很详细,重点就在于转移的时候无视lca,只有在计算答案的时候临时加进来lca,算完答案再把lca去掉。

  1 /**************************************************************
  2     Problem: 3757
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:17180 ms
  7     Memory:17716 kb
  8 ****************************************************************/
  9
 10 //BZOJ 3757
 11 #include<cmath>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 using namespace std;
 21 void read(int &v){
 22     v=0; int sign=1; char ch=getchar();
 23     while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();}
 24     while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();}
 25     v*=sign;
 26 }
 27 #define debug
 28 /******************tamplate*********************/
 29 const int N=100010;
 30 int head[N],to[N],next[N],cnt;
 31 void add(int x,int y){
 32     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
 33     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
 34 }
 35 /*******************edge************************/
 36 int n,m,color[N],root;
 37 int B,belong[N],st[N],top,tot,deep[N];
 38 int fa[N][20],bin[25];
 39 void dfs(int x){
 40     int bottom=top;
 41     for(int i=1;i<=16;i++)
 42         if(deep[x]>=bin[i])
 43             fa[x][i]=fa[fa[x][i-1]][i-1];
 44         else break;
 45     for(int i=head[x];i;i=next[i])
 46         if (to[i]!=fa[x][0]){
 47             fa[to[i]][0]=x;
 48             deep[to[i]]=deep[x]+1;
 49             dfs(to[i]);
 50             if (top-bottom>=B){
 51                 ++tot;
 52                 while(top!=bottom)
 53                     belong[st[top--]]=tot;
 54             }
 55         }
 56     st[++top]=x;
 57 }
 58 int LCA(int x,int y){
 59     if (deep[x]<deep[y]) swap(x,y);
 60     int t=deep[x]-deep[y];
 61     for(int i=0;bin[i]<=t;i++)
 62         if (t&bin[i]) x=fa[x][i];
 63     D(i,16,0)
 64         if(fa[x][i]!=fa[y][i])
 65             x=fa[x][i],y=fa[y][i];
 66     if(x==y) return x;
 67     return fa[x][0];
 68 }
 69 /*******************dfs&&LCA********************/
 70 struct ques{
 71     int x,y,a,b,num;
 72     bool operator < (const ques &now)const{
 73         if (belong[x]==belong[now.x]) return belong[y]<belong[now.y];
 74         else return belong[x]<belong[now.x];
 75     }
 76 }Q[N];
 77
 78 int num[N],ans=0,ANS[N];
 79 bool used[N];
 80 inline void work(int x){
 81     if(!used[x]){
 82         num[color[x]]++;used[x]=1;
 83         if(num[color[x]]==1) ans++;
 84     }
 85     else{
 86         num[color[x]]--;used[x]=0;
 87         if(num[color[x]]==0) ans--;
 88     }
 89 }
 90
 91 void Xor(int x,int y){
 92     int lca=LCA(x,y);
 93     while(x!=lca) {work(x); x=fa[x][0];}
 94     while(y!=lca) {work(y); y=fa[y][0];}
 95 }
 96
 97 int main(){
 98     bin[0]=1; F(i,1,20) bin[i]=bin[i-1]<<1;
 99
100     read(n); read(m);
101     B=sqrt(n);
102     F(i,1,n) read(color[i]);
103     int x,y;
104     F(i,1,n){
105         read(x); read(y);
106         if (x==0) root=y;
107         if (y==0) root=x;
108         add(x,y);
109     }
110     dfs(root);
111     tot++;
112     while(top)belong[st[top--]]=tot;
113
114     int a,b;
115     F(i,1,m){
116         read(x); read(y); read(a); read(b);
117         Q[i]=(ques){x,y,a,b,i};
118     }
119     sort(Q+1,Q+m+1);
120     //转移的时候不考虑LCA,查答案的时候临时算进来,计算完答案后再把LCA删掉
121     int lca=(LCA(Q[1].x,Q[1].y));
122     Xor(Q[1].x,Q[1].y);
123     work(lca);
124     ANS[Q[1].num]=ans;
125     if (num[Q[1].a]!=0 && num[Q[1].b]!=0 && Q[1].a!=Q[1].b) ANS[Q[1].num]--;
126     work(lca);
127     F(i,2,m){
128         Xor(Q[i-1].x,Q[i].x);
129         Xor(Q[i-1].y,Q[i].y);
130         lca=LCA(Q[i].x,Q[i].y);
131         work(lca);
132         ANS[Q[i].num]=ans;
133         if(num[Q[i].a]!=0 && num[Q[i].b]!=0 && Q[i].a!=Q[i].b) ANS[Q[i].num]--;
134         work(lca);
135     }
136     F(i,1,m) printf("%d\n",ANS[i]);
137     return 0;
138 }

时间: 2024-08-16 17:06:02

【BZOJ】【3757】苹果树的相关文章

bzoj 3757: 苹果树(树上莫队)

3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 1327  Solved: 510 [Submit][Status][Discuss] Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色.我们用一个1到n之间的正整数来表示一种颜色

bzoj 3757 苹果树(树上莫队算法)

[题意] 有若干个询问,询问路径u,v上的颜色总数,另外有要求a,b,意为将a颜色看作b颜色. [思路] vfk真是神系列233. Quote: 用S(v, u)代表 v到u的路径上的结点的集合. 用root来代表根结点,用lca(v, u)来代表v.u的最近公共祖先. 那么 S(v, u) = S(root, v) xor S(root, u) xor lca(v, u) 其中xor是集合的对称差. 简单来说就是节点出现两次消掉. lca很讨厌,于是再定义 T(v, u) = S(root,

BZOJ 3757 苹果树 树上莫队

题目大意:给出一棵树,问任意两点之间有多少种不同的颜色,一个人可能会有色盲,会将A和B当成一种颜色. 思路:比较裸的树上莫队,写出来之后,很慢,怀疑是分块的缘故,然后果断找了当年比赛的标称交上去,瞬间rk1,大概看了一眼,他好像是直接用DFS序+曼哈顿距离最小生成树搞的,为什么会比分块快? 昨天下午看到这个题之后就一直在研究树上莫队的正确姿势,然后先写了树分块,后来看了很多牛人的SPOJ COT2的题解,后来又和同学探讨了好久才弄明白. 首先先将树分块,然后把区间排序,按照第一权值为左端点所在块

【BZOJ】3757 苹果树

题意:n个节点的树,每个点有一种颜色.现有m种询问,每次询问x y a b表示x到y的路径上颜色的种数且a颜色看成b颜色.(n<=50000, m<=100000) #include <bits/stdc++.h> using namespace std; const int N=50005; int ihead[N], cnt, id[N], blo[N], f[N][16], dep[N], cal[N], col[N], st[N], n, m, Ans[N], ans, I

bzoj 3757 树上莫队

感谢以下文章作者: http://blog.csdn.net/kuribohg/article/details/41458639 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ http://blog.csdn.net/jiangyuze831/article/details/41476865 http://hzwer.com/5259.html 做了树上的莫队,感觉对这个算法的思想理解更深了 先分块,不论怎

BZOJ - 3757 树上莫队解决离线路径问题 &amp; 学习心得

题意:给你一棵树,求u,v最短路径的XXX(本题是统计权值种类) 今天课上摸鱼学了一种有意思的处理路径方式(其实是链式块状树翻车了看别的),据说实际运行跑的比XX记者还快 大概就是像序列莫队那样 首先是对暴力查询的优化 第一关键字是块(树上分块),第二关键字是dfs序,这样保证了离线操作的下界最优 其次是转移的优化 我把大佬的话再转述一遍: 设\(S(u,v)\):\(u-v\)最短路径所覆盖的点集 \(S(u,v)=S(root,u)⊕S(root,v)⊕lca(u,v)\) 记\(T(u,v

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

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()

【BZOJ-3757】苹果树 块状树 + 树上莫队

3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色.我们用一个到n之间的正整数来表示一种颜色.树上

bzoj 3052: [wc2013]糖果公园(带修改的树上莫队)

3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MB Submit: 892  Solved: 425 [Submit][Status][Discuss] Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT Source [Submit][Status][Discuss] 题解:bzoj 2120 和 bzoj 37