题目分析:

考虑欧拉序,这里的欧拉序与ETT欧拉序的定义相同而与倍增LCA不同。然后不妨对于询问$u$与$v$让$dfsin[u] \leq dfsin[v]$,这样对于u和v不在一条路径上,它们可以改成询问$dfsin[u]$到$dfsin[v]$。否则改成$dfsout[u]$到$dfsin[v]$,并加上LCA上的影响,如果在询问过程中没有加入就加入,否则删除。

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int maxm = ;
const int srt = ; int n,m;
int a[maxn],tb[maxn],arr[maxn],fa[maxn],pm[maxm],ans[maxm];
int dfsin[maxn],dfsout[maxn],Num,pre[maxn];
vector <int> g[maxn];
vector <pair<int,int> > Qy[maxn];
struct query{int l,r,bel,rem;}Q[maxm]; int found(int x){
int rx = x; while(pre[rx] != rx) rx = pre[rx];
while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;}
return rx;
} void dfs(int now,int ff){
arr[now] = ;pm[++Num] = now;fa[now] = ff;
dfsin[now] = Num;
for(int i=;i<Qy[now].size();i++){
if(!arr[Qy[now][i].first])continue;
Q[Qy[now][i].second].bel=found(Qy[now][i].first);
}
for(int i=;i<g[now].size();i++){
if(g[now][i]==fa[now])continue;
dfs(g[now][i],now);
}
pre[now] = fa[now];
pm[++Num] = now; dfsout[now] = Num;
} void read(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]),tb[i] = a[i];
sort(tb+,tb+n+); int num=unique(tb+,tb+n+)-tb-;
for(int i=;i<=n;i++) a[i]=lower_bound(tb+,tb+num+,a[i])-tb;
memset(tb,,sizeof(tb));
for(int i=;i<n;i++){
int u,v; scanf("%d%d",&u,&v);
g[u].push_back(v); g[v].push_back(u);
}
for(int i=;i<=m;i++) scanf("%d%d",&Q[i].l,&Q[i].r);
} int cmp(query alpha,query beta){
if(alpha.l/srt == beta.l/srt) return alpha.r < beta.r;
else return alpha.l/srt < beta.l/srt;
} void init(){
for(int i=;i<=m;i++){
Qy[Q[i].l].push_back(make_pair(Q[i].r,i));
Qy[Q[i].r].push_back(make_pair(Q[i].l,i));
}
for(int i=;i<=n;i++) pre[i] = i;
dfs(,);
for(int i=;i<=m;i++){
if(dfsin[Q[i].l] > dfsin[Q[i].r]) swap(Q[i].l,Q[i].r);
if(Q[i].bel == Q[i].l || Q[i].bel == Q[i].r){
Q[i].l = dfsin[Q[i].l]; Q[i].r = dfsin[Q[i].r];
Q[i].bel = i; Q[i].rem = ;
}else{
Q[i].l = dfsout[Q[i].l]; Q[i].r = dfsin[Q[i].r];
Q[i].rem = Q[i].bel; Q[i].bel = i;
}
}
sort(Q+,Q+m+,cmp);
} void work(){
int L = ,R = ,as=; tb[a[]]++;
for(int i=;i<=m;i++){
int nowl = Q[i].l,nowr = Q[i].r;
while(R < nowr){
R++;
if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){
if(!tb[a[pm[R]]])as++;
tb[a[pm[R]]]++;
}else{
if(tb[a[pm[R]]] == ) as--;
tb[a[pm[R]]]--;
}
}
while(L > nowl){
L--;
if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){
if(!tb[a[pm[L]]])as++;
tb[a[pm[L]]]++;
}else{
if(tb[a[pm[L]]] == ) as--;
tb[a[pm[L]]]--;
}
}
while(R > nowr){
if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){
if(tb[a[pm[R]]] == ) as--;
tb[a[pm[R]]]--;
}else{
if(!tb[a[pm[R]]])as++;
tb[a[pm[R]]]++;
}
R--;
}
while(L < nowl){
if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){
if(tb[a[pm[L]]] == ) as--;
tb[a[pm[L]]]--;
}else{
if(!tb[a[pm[L]]])as++;
tb[a[pm[L]]]++;
}
L++;
}
if(Q[i].rem && !tb[a[Q[i].rem]])ans[Q[i].bel]=as+;
else ans[Q[i].bel] = as;
}
for(int i=;i<=m;i++) printf("%d\n",ans[i]);
} int main(){
read();
init();
work();
return ;
}

SPOJ10707 COT2 - Count on a tree II 【树上莫队】的更多相关文章

  1. spoj COT2 - Count on a tree II 树上莫队

    题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的,  受益匪浅.. #include <iostream> #include < ...

  2. SP10707 COT2 - Count on a tree II (树上莫队)

    大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...

  3. SP10707 COT2 - Count on a tree II [树上莫队学习笔记]

    树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...

  4. SPOJ COT2 Count on a tree II 树上莫队算法

    题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...

  5. [SPOJ]Count on a tree II(树上莫队)

    树上莫队模板题. 使用欧拉序将树上路径转化为普通区间. 之后莫队维护即可.不要忘记特判LCA #include<iostream> #include<cstdio> #incl ...

  6. 【SPOJ10707】 COT2 Count on a tree II

    SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...

  7. 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  ...

  8. COT2 - Count on a tree II(树上莫队)

    COT2 - Count on a tree II You are given a tree with N nodes. The tree nodes are numbered from 1 to N ...

  9. 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 ...

随机推荐

  1. mariadb(第五章)视图、事物、索引、外键

    视图 对于复杂的查询,在多个地方被使用,如果需求发生了改变,需要更改sql语句,则需要在多个地方进行修改,维护起来非常麻烦 假如因为某种需求,需要将user拆房表usera和表userb,该两张表的结 ...

  2. 基于linux下的krpano的使用

    鉴于目前网络上关于krpano的使用和介绍少之又少,结合自己的学习和使用经历,做个总结和记录. 1.安装 下载地址: linux https://krpano.com/forum/wbb/index. ...

  3. Maven安装与环境配置(Windows)

    1.下载安装包 在Maven官网下载最新版的安装包:http://maven.apache.org/download.cgi 2.解压安装包 3.配置Maven环境变量 配置M2_HOME环境变量,指 ...

  4. centos7下安装python3.6

    一.wget 官网下载到本地 进入家目录: cd ~ wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz下载到本地 解压移动到/ ...

  5. PHP安装pecl扩展--通用

    虽然现在composer很流行,但是有时候,我们还是要安装pecl的扩展. pecl扩展可以在pecl.php.net中查看,想要什么扩展,可以去搜索,比如xdebug.siege.memcached ...

  6. MySQL慢查询日志配置方式 slow_query_log

    MySQL慢查询(一) - 开启慢查询 - 鲁玉成 - 博客园 https://www.cnblogs.com/luyucheng/p/6265594.html mysql开启慢查询方法 - lava ...

  7. Linux&Windows中VNC协议及使用方法

    [转载]window下使用vnc远程登录ubuntu/linux图形界面_五个粽子_新浪博客http://blog.sina.com.cn/s/blog_677265f601012mqg.html V ...

  8. MySQL 5.7默认ONLY_FULL_GROUP_BY语义介绍

    mysql 5.7版本 出现 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corre ...

  9. 手机移动端input date placehoder不显示

    要解决这个问题,我们可以伪造一个placehoder,通过css跟js来解决这个问题. 为什么要用js的原因是因为当你选择了时间之后,placehoder的文字没有清除掉,所以我们就需要把这个伪造的p ...

  10. [转帖]system()、exec()、fork()三个与进程有关的函数的比较

    system().exec().fork()三个与进程有关的函数的比较 https://www.cnblogs.com/qingergege/p/6601807.html 启动新进程(system函数 ...