SPOJ - COT2 离线路径统计
题意:求\(u\)到\(v\)的最短路径的不同权值种类个数
树上莫队试水题,这一篇是上篇的弱化部分,但可测试以下结论的正确性
设\(S(u,v)\):\(u-v\)最短路径所覆盖的点集
\(S(u,v)=S(root,u)⊕S(root,v)⊕lca(u,v)\)
记\(T(u,v)=S(root,u)⊕S(root,v)\)
每次转移我们只考虑\(T\)的部分,\(lca\)单独处理
对于某一次距离为1的转移,如\(u→u'\)
\(T(u,u')=S(root,u)⊕S(root,u')\)
\(T(u',v)=S(root,u')⊕S(root,v)\)
\(T(u',v)=S(root,u)⊕S(root,v)⊕S(root,u)⊕S(root,u')=T(u,v)⊕T(u,u')\)
得出结论\(T(u',v)=T(u,v)⊕T(u,u')\)
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 2e5+11;
const int INF = 0x7fffffff;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
int color[MAXN],belong[MAXN],depth[MAXN],dfn[MAXN];
int stk[MAXN],bit[32],limit,root,cnt,CLOCK,top;
int anc[MAXN][20];
map<int,int> haxi;
bool vis[MAXN];
int ANS,cntNum[MAXN],ans[MAXN];
struct QQQ{
int u,v,id;
bool operator < (const QQQ &rhs) const{
if(belong[u]!=belong[rhs.u]){
return belong[u]<belong[rhs.u];
}else{
return dfn[v]<dfn[rhs.v];
}
}
}Q[MAXN];
int dfs(int u,int fa,int d){
dfn[u]=++CLOCK;
anc[u][0]=fa; depth[u]=d;
rep(i,1,16){
if(depth[u]<bit[i]) break;
anc[u][i]=anc[anc[u][i-1]][i-1];
}
int num=0;
erep(i,u){
int v=to[i];
if(v==fa) continue;
num+=dfs(v,u,d+1);
if(num>=limit){
++cnt;
rep(i,1,num) belong[stk[top--]]=cnt;
num=0;
}
}
stk[++top]=u; num++;
return num;
}
int lca(int u,int v){
if(depth[u]<depth[v]) swap(u,v);
int d=depth[u]-depth[v];
for(int i=0;bit[i]<=d;i++){
if(d>>i&1) u=anc[u][i];
}
for(int i=16;i>=0;i--){
if(anc[u][i]!=anc[v][i]){
u=anc[u][i];
v=anc[v][i];
}
}
if(u==v) return u;
else return anc[u][0];
}
void rev(int u){
if(!vis[u]){
vis[u]=1;
if(cntNum[color[u]]==0) ANS++;
cntNum[color[u]]++;
}else{
vis[u]=0;
if(cntNum[color[u]]==1) ANS--;
cntNum[color[u]]--;
}
}
void viss(int u,int v){
while(u!=v){
if(depth[u]>depth[v]) rev(u),u=anc[u][0];
else rev(v),v=anc[v][0];
}
}
int main(){
int n,m;
bit[0]=1;rep(i,1,30) bit[i]=bit[i-1]<<1;
while(cin>>n>>m){
init(); limit=sqrt(n)+1;
haxi.clear(); int haxiid=0;
rep(i,1,n){
int t=read();
if(haxi[t]==0) haxi[t]=++haxiid;
color[i]=haxi[t];
}
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v),add(v,u);
}
root=1;
top=cnt=CLOCK=0;
memset(anc,0,sizeof anc);
dfs(root,0,1);
if(top){
cnt++;
while(top) belong[stk[top--]]=cnt;
}
rep(i,1,m){
Q[i].u=read();
Q[i].v=read();
Q[i].id=i;
}
sort(Q+1,Q+1+m); ANS=0;
int t=lca(Q[1].u,Q[1].v);
memset(vis,0,sizeof vis);
viss(Q[1].u,Q[1].v);
rev(lca(Q[1].u,Q[1].v));
ans[Q[1].id]=ANS;
rev(lca(Q[1].u,Q[1].v));
rep(i,2,m){
viss(Q[i-1].u,Q[i].u);
viss(Q[i-1].v,Q[i].v);
rev(lca(Q[i].u,Q[i].v));
ans[Q[i].id]=ANS;
rev(lca(Q[i].u,Q[i].v));
}
rep(i,1,m) println(ans[i]);
}
return 0;
}
SPOJ - COT2 离线路径统计的更多相关文章
- 键盘录入一个文件夹路径,统计该文件夹(包含子文件夹)中每种类型的文件及个数,注意:用文件类型(后缀名,不包含.(点),如:"java","txt")作为key, 用个数作为value,放入到map集合中,遍历map集合
package cn.it.zuoye5; import java.io.File;import java.util.HashMap;import java.util.Iterator;import ...
- 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 ...
- 洛谷——P1608 路径统计
P1608 路径统计 题目描述 “RP餐厅”的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让HZH,TZY去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有N个地方, ...
- 洛谷 P1608 路径统计
P1608 路径统计 题目描述 “RP餐厅”的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让HZH,TZY去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有N个地方, ...
- 某模拟赛C题 树上路径统计 (点分治)
题意 给定一棵有n个节点的无根树,树上的每个点有一个非负整数点权.定义一条路径的价值为路径上的点权和-路径上的点权最大值. 给定参数P,我!=们想知道,有多少不同的树上简单路径,满足它的价值恰好是P的 ...
- SPOJ COT2 树上找路径上不同值的个数
题目大意 给出多个询问u , v , 求出u-v路径上点权值不同的个数 开始做的是COT1,用主席树写过了,理解起来不难 很高兴的跑去做第二道,完全跟普通数组区间求k个不同有很大区别,完全没思路 膜拜 ...
- 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 (树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...
- 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)
题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...
随机推荐
- Docker学习笔记_安装和使用nginx
一.软件环境 1.宿主机OS:Win10 64位 2.虚拟机OS:Ubuntu 18.04,虚拟机IP:192.168.8.25 3.Docker安装在虚拟机Ubuntu 18.04上 二.安装过程 ...
- How to install Freemind 1.0.1 to Ubuntu 14
安装了Freemind0.9后发现不能打开windows的1.0.1保存的*.mm文件,便对版本开始升级. 1. 从http://freemind.sourceforge.net/wiki/index ...
- Django--form保存用户输入内容
需求 用户提交form时,如果报错,页面中的用户信息还在(除了密码),没有被刷新掉,不用用户再次输入. 速查 views.py 1 2 3 def login(request): obj = ...
- 当鼠标悬停在链接上,或者点击过的链接,颜色会被设置为 #2a6496。同时,会呈现一条下划线。点击过的链接,会呈现一个颜色码为 #333 的细的虚线轮廓。另一条规则是设置轮廓为 5 像素宽,且对于基于 webkit 浏览器有一个 -webkit-focus-ring-color 的浏览器扩展。轮廓偏移设置为 -2 像素
a:hover, a:focus { color: #2a6496; text-decoration: underline; } a:focus { outline: thin dotted #333 ...
- App常用性能测试工具清单
APP的CPU,内存,耗电,流量测试工具 APP的CPU,内存,耗电,流量测试工具下载地址,后续文章会介绍如何使用Emmagee.itest.gt APP应用的CPU,内存,耗电,流量调查(可和同类产 ...
- clojure-emacs-autocomplete
1. https://github.com/clojure-emacs/cider#keyboard-shortcuts 2. install emacs 24.5 3. http://clojure ...
- cocos学习
第一章 JavaScript 快速入门 1.1 变量 在 JavaScript 中,我们像这样声明一个变量: var a; 保留字 var 之后紧跟着的,就是一个变量名,接下来我们可以为变量赋值: v ...
- angular学习文章
https://www.jianshu.com/p/86c6249a2069 angular.cn https://segmentfault.com/a/1190000008754631
- javascript 视频播放指定的时间段
javascript 视频播放指定的时间段 一.html5 vedio: //指定开始时间 player.currentTime=startPoint; player.play(); //使用事件来控 ...
- 为openstack服务使能debug模式
Most OpenStack services use the same configuration options to enable the debug logging that is also ...