[SPOJ]COT2
题意:给一棵带点权的树,多次询问两点间路径上的不同权值数
学习了一下莫队上树(雾
先求出栈入栈序$p_{1\cdots 2n}$,记$st_x$为$x$在$p$中第一次出现的位置,$ed_x$为$x$在$p$中最后一次出现的位置
对于一个询问$(x,y)$,先令$st_x\lt st_y$,求出其$lca$,若$x=lca$,则询问$[st_x,st_y]$,否则询问$[ed_x,st_y]$还有$lca$(因为$[ed_x,st_y]$不包含$lca$)
于是我们成功地把问题转化到序列上,普通地莫队即可
不应处理出现两次的数(因为它入栈一次,出栈一次,在路径之外)
#include<stdio.h> #include<algorithm> #include<map> #include<math.h> using namespace std; struct ask{ int l,r,lca,sid,qid; }q[100010]; int to[80010],nex[80010],h[40010],dep[40010],fa[40010][16],v[40010],p[80010],st[40010],ed[40010],ti[40010],ex[40010],ans[100010],M; map<int,int>mp; map<int,int>::iterator it; bool cmp(ask a,ask b){ if(a.sid==b.sid)return a.r<b.r; return a.sid<b.sid; } void add(int a,int b){ M++; to[M]=b; nex[M]=h[a]; h[a]=M; } void dfs(int x){ st[x]=++M; p[M]=x; for(int i=h[x];i;i=nex[i]){ if(to[i]!=fa[x][0]){ fa[to[i]][0]=x; dep[to[i]]=dep[x]+1; dfs(to[i]); } } ed[x]=++M; p[M]=x; } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); int i; for(i=15;i>=0;i--){ if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; } if(x==y)return x; for(i=15;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int sum; void add(int); void del(int x){ if(ex[x]==0)return add(x); ti[v[x]]--; if(ti[v[x]]==0)sum--; ex[x]=0; } void add(int x){ if(ex[x])return del(x); if(ti[v[x]]==0)sum++; ti[v[x]]++; ex[x]=1; } int main(){ int n,m,i,j,x,y,l,r,sq; scanf("%d%d",&n,&m); sq=sqrt(n); for(i=1;i<=n;i++){ scanf("%d",v+i); mp[v[i]]=1; } for(i=1,it=mp.begin();it!=mp.end();it++,i++)it->second=i; for(i=1;i<=n;i++)v[i]=mp[v[i]]; for(i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } M=0; dep[1]=1; dfs(1); for(j=1;j<16;j++){ for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1]; } for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); if(st[x]>st[y])swap(x,y); j=lca(x,y); q[i].r=st[y]; if(x==j) q[i].l=st[x]; else{ q[i].l=ed[x]; q[i].lca=j; } q[i].sid=q[i].l/sq; q[i].qid=i; } sort(q+1,q+m+1,cmp); l=r=1; add(1); for(i=1;i<=m;i++){ while(l>q[i].l){ l--; add(p[l]); } while(r<q[i].r){ r++; add(p[r]); } while(l<q[i].l){ del(p[l]); l++; } while(r>q[i].r){ del(p[r]); r--; } if(q[i].lca)add(q[i].lca); ans[q[i].qid]=sum; if(q[i].lca)del(q[i].lca); } for(i=1;i<=m;i++)printf("%d\n",ans[i]); }
[SPOJ]COT2的更多相关文章
- SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)
COT2 - Count on a tree II #tree You are given a tree with N nodes. The tree nodes are numbered from ...
- SPOJ COT2 Count on a tree II(树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ You are given a tree with N nodes.The tree nodes are numbere ...
- spoj COT2 - Count on a tree II
COT2 - Count on a tree II http://www.spoj.com/problems/COT2/ #tree You are given a tree with N nodes ...
- SPOJ COT2 Count on a tree II (树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...
- SPOJ COT2 树上找路径上不同值的个数
题目大意 给出多个询问u , v , 求出u-v路径上点权值不同的个数 开始做的是COT1,用主席树写过了,理解起来不难 很高兴的跑去做第二道,完全跟普通数组区间求k个不同有很大区别,完全没思路 膜拜 ...
- spoj COT2 - Count on a tree II 树上莫队
题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的, 受益匪浅.. #include <iostream> #include < ...
- spoj COT2(树上莫队)
模板.树上莫队的分块就是按dfn分,然后区间之间转移时注意一下就好.有个图方便理解http://blog.csdn.net/thy_asdf/article/details/47377709: #in ...
- 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)
题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...
- SPOJ - COT2 离线路径统计
题意:求\(u\)到\(v\)的最短路径的不同权值种类个数 树上莫队试水题,这一篇是上篇的弱化部分,但可测试以下结论的正确性 设\(S(u,v)\):\(u-v\)最短路径所覆盖的点集 \(S(u,v ...
随机推荐
- 【翻译】为什么Java中的String不可变
笔主前言: 众所周知,String是Java的JDK中最重要的基础类之一,在笔主心中的地位已经等同于int.boolean等基础数据类型,是超越了一般Object引用类型的高端大气上档次的存在. 但是 ...
- taotao单点登录的用户Controller、service(注册、登录、验证是否登录方法)
接口文档: 1.1. 注册接口 1.1.1. 检查数据是否可用 请求方法 GET URL http://sso.taotao.com/user/check/{param}/{type} 参数说明 格式 ...
- Jquery 获取checkbox的checked问题以及解决方案
转载自:http://www.cnblogs.com/-run/archive/2011/11/16/2251250.html 这个郁闷了,今天写这个功能的时候发现了问题,上网找了好多资料对照,更加纠 ...
- Sencha Touch2 -- 11.1:定义具有关联关系的模型
在Sencha Touch2.0中,可以定义不同模型之间的关联关系.例如,在开发博客网站的时候,可以首先定义用户(User)模型,然后为用户定义文章(Article)模型.一个用户可以发表多篇文章,因 ...
- 动态规划:DAG-嵌套矩形
据说DAG是动态规划的基础,想一想还真的是这样的,动态规划的所有状态和转移都可以归约成DAG DAG有两个典型模型,一个是嵌套矩形问题一个是硬币问题,这里仅介绍一个嵌套矩形问题 等二轮复习的时候再补上 ...
- C#网络编程基本字段---IPAddress、IPEndPoint
命名空间: using System.Net; PAddress类提供了对IP地址的转换.处理等功能.其Parse方法可将IP地址字符串转换为IPAddress实例. 如:IPAddress ip = ...
- 【转载】字符串最小表示法-O(n)算法
原博客链接:http://blog.csdn.net/zy691357966/article/details/39854359 未授权,侵权删. 因为这篇博客写得真好..转载了.. 红色的字是原博主写 ...
- 【Foreign】划分序列 [线段树][DP]
划分序列 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...
- COGS2642 / Bzoj4590 [Shoi2015]自动刷题机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 906 Solved: 321 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了 ...
- 【洛谷 P1653】 猴子 (并查集)
题目链接 没删除调试输出,原地炸裂,\(80\)->\(0\).如果你要问剩下的\(20\)呢?答:数组开小了. 这题正向删边判连通性是很不好做的,因为我们并不会并查集的逆操作.于是可以考虑把断 ...