SPOJ10707 COT2 - Count on a tree II 【树上莫队】

题目分析:

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

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3
  4 const int maxn = 40200;
  5 const int maxm = 101000;
  6 const int srt = 325;
  7
  8 int n,m;
  9 int a[maxn],tb[maxn],arr[maxn],fa[maxn],pm[maxm],ans[maxm];
 10 int dfsin[maxn],dfsout[maxn],Num,pre[maxn];
 11 vector <int> g[maxn];
 12 vector <pair<int,int> > Qy[maxn];
 13 struct query{int l,r,bel,rem;}Q[maxm];
 14
 15 int found(int x){
 16     int rx = x; while(pre[rx] != rx) rx = pre[rx];
 17     while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;}
 18     return rx;
 19 }
 20
 21 void dfs(int now,int ff){
 22     arr[now] = 1;pm[++Num] = now;fa[now] = ff;
 23     dfsin[now] = Num;
 24     for(int i=0;i<Qy[now].size();i++){
 25     if(!arr[Qy[now][i].first])continue;
 26     Q[Qy[now][i].second].bel=found(Qy[now][i].first);
 27     }
 28     for(int i=0;i<g[now].size();i++){
 29     if(g[now][i]==fa[now])continue;
 30     dfs(g[now][i],now);
 31     }
 32     pre[now] = fa[now];
 33     pm[++Num] = now; dfsout[now] = Num;
 34 }
 35
 36 void read(){
 37     scanf("%d%d",&n,&m);
 38     for(int i=1;i<=n;i++) scanf("%d",&a[i]),tb[i] = a[i];
 39     sort(tb+1,tb+n+1);  int num=unique(tb+1,tb+n+1)-tb-1;
 40     for(int i=1;i<=n;i++) a[i]=lower_bound(tb+1,tb+num+1,a[i])-tb;
 41     memset(tb,0,sizeof(tb));
 42     for(int i=1;i<n;i++){
 43     int u,v; scanf("%d%d",&u,&v);
 44     g[u].push_back(v); g[v].push_back(u);
 45     }
 46     for(int i=1;i<=m;i++) scanf("%d%d",&Q[i].l,&Q[i].r);
 47 }
 48
 49 int cmp(query alpha,query beta){
 50     if(alpha.l/srt == beta.l/srt) return alpha.r < beta.r;
 51     else return alpha.l/srt < beta.l/srt;
 52 }
 53
 54 void init(){
 55     for(int i=1;i<=m;i++){
 56     Qy[Q[i].l].push_back(make_pair(Q[i].r,i));
 57     Qy[Q[i].r].push_back(make_pair(Q[i].l,i));
 58     }
 59     for(int i=1;i<=n;i++) pre[i] = i;
 60     dfs(1,0);
 61     for(int i=1;i<=m;i++){
 62     if(dfsin[Q[i].l] > dfsin[Q[i].r]) swap(Q[i].l,Q[i].r);
 63     if(Q[i].bel == Q[i].l || Q[i].bel == Q[i].r){
 64         Q[i].l = dfsin[Q[i].l]; Q[i].r = dfsin[Q[i].r];
 65         Q[i].bel = i; Q[i].rem = 0;
 66     }else{
 67         Q[i].l = dfsout[Q[i].l]; Q[i].r = dfsin[Q[i].r];
 68         Q[i].rem = Q[i].bel; Q[i].bel = i;
 69     }
 70     }
 71     sort(Q+1,Q+m+1,cmp);
 72 }
 73
 74 void work(){
 75     int L = 1,R = 1,as=1; tb[a[1]]++;
 76     for(int i=1;i<=m;i++){
 77     int nowl = Q[i].l,nowr = Q[i].r;
 78     while(R < nowr){
 79         R++;
 80         if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){
 81         if(!tb[a[pm[R]]])as++;
 82         tb[a[pm[R]]]++;
 83         }else{
 84         if(tb[a[pm[R]]] == 1) as--;
 85         tb[a[pm[R]]]--;
 86         }
 87     }
 88     while(L > nowl){
 89         L--;
 90         if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){
 91         if(!tb[a[pm[L]]])as++;
 92         tb[a[pm[L]]]++;
 93         }else{
 94         if(tb[a[pm[L]]] == 1) as--;
 95         tb[a[pm[L]]]--;
 96         }
 97     }
 98     while(R > nowr){
 99         if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){
100         if(tb[a[pm[R]]] == 1) as--;
101         tb[a[pm[R]]]--;
102         }else{
103         if(!tb[a[pm[R]]])as++;
104         tb[a[pm[R]]]++;
105         }
106         R--;
107     }
108     while(L < nowl){
109         if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){
110         if(tb[a[pm[L]]] == 1) as--;
111         tb[a[pm[L]]]--;
112         }else{
113         if(!tb[a[pm[L]]])as++;
114         tb[a[pm[L]]]++;
115         }
116         L++;
117     }
118     if(Q[i].rem && !tb[a[Q[i].rem]])ans[Q[i].bel]=as+1;
119     else ans[Q[i].bel] = as;
120     }
121     for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
122 }
123
124 int main(){
125     read();
126     init();
127     work();
128     return 0;
129 }

原文地址:https://www.cnblogs.com/Menhera/p/9545896.html

时间: 2024-10-01 02:42:53

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

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

参考博客 对于树上的路径询问问题 O(1)的时间加入或删除一个点的贡献 -> \(O(n\sqrt n)\)的复杂度求出所有询问的答案 对树上的结点进行分块,离线询问后排序,顺序遍历暴力转移路径(转移时加入或删除路径上的点的贡献即可). 关于转移路径:首先定义路径:设\(T_u\)为\(u\) 到根的路径上边的集合,那么\(u\)到\(v\) 的路径上的边的集合就是\(T_u \triangle T_v\) (\(\triangle\) 是对称差).要从\(u\rightarrow v\) 转移

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

题目链接(同上一题苹果树) 为什么第10个点T了一晚上.. 下面那个却AC了?跑的也不慢. TLE: /* 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() //#define gc() (SS==TT&&(TT=(SS

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. The tree nodes are numbered from 1 to N. Each node has an integer weight. We will ask you to perform the following operation: u v : ask for how many

「SPOJ10707」Count on a tree II

「SPOJ10707」Count on a tree II 传送门 树上莫队板子题. 锻炼基础,没什么好说的. 参考代码: #include <algorithm> #include <cstdio> #include <cmath> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w

SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)

题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无意中看到树上莫队,只是拿来练练,没有想到这题的难点不在于树上莫队,而是判断LCA是否在两点之间的路径上的问题.耗时1天. 树上莫队的搞法就是: (1)DFS一次,对树进行分块,分成sqrt(n)块,每个点属于一个块.并记录每个点的DFS序. (2)将m个询问区间用所属块号作为第一关键字,DFS序作为第二关键字

【SPOJ10707】COT2 - Count on a tree II

题目大意:给定一棵 N 个节点的无根树,每个节点有一个颜色.现有 M 个询问,每次询问一条树链上的不同颜色数. 题解:学会了树上莫队. 树上莫队是将节点按照欧拉序进行排序,将树上问题转化成序列上的问题进行求解的算法.需要分两种情况进行讨论,第一种情况是对于询问 x,y 来说,x 为 y 的祖先,则询问的区间为 \(st[x],st[y]\),第二种情况是 x 与 y 处在两个不同的子树内,这时发现 \(lca(x,y)\) 的欧拉序并不在 [ed[x], st[y]] 内,因此需要额外考虑 lc

SPOJ:COT2 Count on a tree II

题意 给定一个n个节点的树,每个节点表示一个整数,问u到v的路径上有多少个不同的整数. n=40000,m=100000 Sol 树上莫队模板题 # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; const int _(1e5 + 5); typedef long long ll; I

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 numbered from 1 to N.Each node has an integer weight. We will ask you to perfrom the following operation: u v : ask for how many different integers that repr

Count on a tree II(树上莫队)

Count on a tree II(luogu) Description 题目描述 给定一个n个节点的树,每个节点表示一个整数,问u到v的路径上有多少个不同的整数. 输入格式 第一行有两个整数n和m(n=40000,m=100000). 第二行有n个整数.第i个整数表示第i个节点表示的整数. 在接下来的n-1行中,每行包含两个整数u v,描述一条边(u,v). 在接下来的m行中,每一行包含两个整数u v,询问u到v的路径上有多少个不同的整数. 输出格式 对于每个询问,输出结果. Solutio