codeforces 221 div1 D Tree and Queries
2014-02-27 17:18
381 查看
题目大意:给一棵树,1为根,每个节点有一个权值。多次询问,每次询问为一个v和k。把v为根的这棵树中,所有节点的权加入一个集合。求,这个集合中,有几种数字出现的次数大于等于k。
最开始,老是去想可持续化数据结构,但是,我不会可持续化的平衡树啊 -_-|||
然后去找解题,有种看起来很叼的暴力算法,但是我看不懂啊。。。
最后,一位大神告诉我这是莫队算法。这里十分感谢这位大神。
我们还是使用欧拉序列把树形结构变成线性结构,问题变成了区间查询问题。
莫队算法算的上是对区间询问问题的一种离线的方法。
我们以无修改值的区间求和为例。
首先说一种最暴力的办法,即将区间每个点都加起来。当然,这是要超时的。
好吧,我们改进一下,假设有两次查询(第一次记为[l1,r1] ,第二次记为[l2,r2])。第一次还是暴力,第二次建立在第一次的结果上,当移动左右边界即可,复杂度为O(|l1-l2|+lr1-r2l)。如果有多次,还是按移动左右边界的方法。
这方法也不靠谱啊,感觉要超时。读者先不要着急。
我们计算前,先对多次查询排个序。假设数组有n个元素,记 int S=sqrt(n),询问的区间为[l,r],排序的的第一关键值为 l/S,第二关键值为 r。
排好序后,再按上面那种做法写,综合复杂度即为n*sqrt(n)。
下面说说为什么是n*sqrt(n)。
按第一关键值排序,等于把查询分成了sqrt(n)块。
对于每一块,每次左边界的移动次数是不会超过sqrt(n)的。在每一块中,按r从小到大排序(即r不降),那么,对于这一块,右边界的均摊复杂度最坏为O(n)。
而从一块移动到另一块,左右边界的移动次数也是不超过n次。
总共有sqrt(n)块,综合复杂度不会超过n*sqrt(n)。
和大神比起来,代码好丑啊。。。
最开始,老是去想可持续化数据结构,但是,我不会可持续化的平衡树啊 -_-|||
然后去找解题,有种看起来很叼的暴力算法,但是我看不懂啊。。。
最后,一位大神告诉我这是莫队算法。这里十分感谢这位大神。
我们还是使用欧拉序列把树形结构变成线性结构,问题变成了区间查询问题。
莫队算法算的上是对区间询问问题的一种离线的方法。
我们以无修改值的区间求和为例。
首先说一种最暴力的办法,即将区间每个点都加起来。当然,这是要超时的。
好吧,我们改进一下,假设有两次查询(第一次记为[l1,r1] ,第二次记为[l2,r2])。第一次还是暴力,第二次建立在第一次的结果上,当移动左右边界即可,复杂度为O(|l1-l2|+lr1-r2l)。如果有多次,还是按移动左右边界的方法。
这方法也不靠谱啊,感觉要超时。读者先不要着急。
我们计算前,先对多次查询排个序。假设数组有n个元素,记 int S=sqrt(n),询问的区间为[l,r],排序的的第一关键值为 l/S,第二关键值为 r。
排好序后,再按上面那种做法写,综合复杂度即为n*sqrt(n)。
下面说说为什么是n*sqrt(n)。
按第一关键值排序,等于把查询分成了sqrt(n)块。
对于每一块,每次左边界的移动次数是不会超过sqrt(n)的。在每一块中,按r从小到大排序(即r不降),那么,对于这一块,右边界的均摊复杂度最坏为O(n)。
而从一块移动到另一块,左右边界的移动次数也是不超过n次。
总共有sqrt(n)块,综合复杂度不会超过n*sqrt(n)。
和大神比起来,代码好丑啊。。。
//#pragma comment(linker, "/STACK:102400000,102400000") #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<cmath> #include<cctype> #include<string> #include<algorithm> #include<iostream> #include<ctime> #include<map> #include<set> using namespace std; #define MP(x,y) make_pair((x),(y)) #define PB(x) push_back(x) typedef __int64 LL; //typedef unsigned __int64 ULL; /* ****************** */ const int INF=1000111222; const double INFF=1e200; const double eps=1e-8; const int mod=1000000007; const int NN=100010; const int MM=10010; /* ****************** */ int a[NN],b[NN]; struct G { int v,next; }E[NN*2]; int p[NN],T,tsp; int ll[NN],rr[NN]; struct Q { int l,r,id,fg,k; }line[NN]; int ans[NN],num[NN],ff[NN]; void add(int u,int v) { E[T].v=v; E[T].next=p[u]; p[u]=T++; } void dfs(int u,int fa) { ll[u]=++tsp; a[tsp]=b[u]; int i,v; for(i=p[u];i+1;i=E[i].next) { v=E[i].v; if(fa==v) continue; dfs(v,u); } rr[u]=tsp; } bool cmp(Q x,Q y) { if(x.fg==y.fg) return x.r<y.r; return x.fg<y.fg; } void solve(int n,int m) { sort(line+1,line+1+m,cmp); int l,r,i; l=1; r=0; for(i=1;i<=m;i++) { while(l>line[i].l) { l--; num[a[l]]++; ff[ num[a[l]] ]++; } while(l<line[i].l) { ff[ num[a[l]] ]--; num[a[l]]--; l++; } while(r>line[i].r) { ff[ num[a[r]] ]--; num[a[r]]--; r--; } while(r<line[i].r) { r++; num[a[r]]++; ff[ num[a[r]] ]++; } ans[ line[i].id ]=ff[ line[i].k ]; } for(i=1;i<=m;i++) { printf("%d\n",ans[i]); } } int main() { memset(p,-1,sizeof(p)); T=tsp=0; int n,m,i,u,v,S; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&b[i]); for(i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs(1,-1); S=sqrt(n+0.0); for(i=1;i<=m;i++) { scanf("%d%d",&v,&line[i].k); line[i].id=i; line[i].l=ll[v]; line[i].r=rr[v]; line[i].fg=ll[v]/S; } solve(n,m); return 0; }
相关文章推荐
- cf#221-div1-D - Tree and Queries-dfs序+莫队算法
- 【Codeforces Round #395 (Div. 2)】Codeforces 764C Timofey and a tree
- Codeforces 375D:Tree and Queries 点化成区间 莫队
- #Codeforces 381 [div2] D. Alyona and a tree 【树链剖分 + 优先队列】
- codeforces 375D:Tree and Queries
- Codeforces Round #371 (Div. 2)C. Sonya and Queries【字典树】
- Tree and Queries CodeForces - 375D 树上莫队
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree
- Codeforces Round #430 (Div. 2) - C. Ilya And The Tree (树形DFS)
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree dfs+set
- VK Cup 2016 - Round 1 (Div. 2 Edition)C. Bear and Forgotten Tree 3(构造)
- CodeForces 713A|Sonya and Queries|字典树|没方法
- VK Cup 2016 - Round 1 (Div. 2 Edition) C. Bear and Forgotten Tree 3 构造
- codeforces水题100道 第十四题 Codeforces Round #321 (Div. 2) A. Kefa and First Steps (brute force)
- codeforces 739b Alyona and a tree
- Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(树上Nim)
- Codeforces 514E. Darth Vader and Tree DP+矩阵快速幂
- Codeforces #277.5 (Div. 2) C. Given Length and Sum of Digits...(简单贪心)
- Codeforces Round #381 (Div. 2) D. Alyona and a tree 树上二分+前缀和思想
- CodeForces 369 div2 E. ZS and The Birthday Paradox 数论