lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs

https://www.luogu.org/problemnew/show/P3379

1.欧拉序+rmq(st)

  1 /*
  2 在这里,对于一个数,选择最左边的
  3 选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
  4 */
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <time.h>
 10 #include <string>
 11 #include <set>
 12 #include <map>
 13 #include <list>
 14 #include <stack>
 15 #include <queue>
 16 #include <vector>
 17 #include <bitset>
 18 #include <ext/rope>
 19 #include <algorithm>
 20 #include <iostream>
 21 using namespace std;
 22 #define ll long long
 23 #define minv 1e-6
 24 #define inf 1e9
 25 #define pi 3.1415926536
 26 #define E  2.7182818284
 27 const ll mod=1e9+7;//998244353
 28 const int maxn=5e5+10;
 29
 30 struct node
 31 {
 32     int d;
 33     node *next;
 34 }*e[maxn];
 35
 36 int s=0;
 37
 38 ///每条边走两遍,n-1条边,走2(n-1)个点
 39 int a[maxn<<1],b[maxn<<1],f[maxn<<1][20],lef[maxn],er[20];
 40 bool vis[maxn]={0};
 41
 42 void dfs(int d,int dep)
 43 {
 44     node* p=e[d];
 45     vis[d]=1;
 46     s++;
 47     lef[d]=s;
 48     a[s]=d;
 49     b[s]=dep;
 50     while (p)
 51     {
 52         if (!vis[p->d])
 53         {
 54             dfs(p->d,dep+1);
 55             s++;
 56             a[s]=d;
 57             b[s]=dep;
 58         }
 59         p=p->next;
 60     }
 61 }
 62
 63 int main()
 64 {
 65     int n,q,root,x,y,i,j,k,m,d;
 66     node *p;
 67     scanf("%d%d%d",&n,&q,&root);
 68     for (i=1;i<n;i++)
 69     {
 70         scanf("%d%d",&x,&y);
 71         p=(node*) malloc (sizeof(node));
 72         p->d=y;
 73         p->next=e[x];
 74         e[x]=p;
 75
 76         p=(node*) malloc (sizeof(node));
 77         p->d=x;
 78         p->next=e[y];
 79         e[y]=p;
 80     }
 81     dfs(root,1);
 82
 83     m=log(s)/log(2);
 84     er[0]=1;
 85     for (i=1;i<=m;i++)
 86         er[i]=er[i-1]<<1;
 87     for (i=1;i<=s;i++)
 88         f[i][0]=i;
 89 //        f[i][0]=b[i];
 90     for (i=1;i<=m;i++)   //2^i
 91         for (j=1,k=j+er[i-1];j<=s-er[i]+1;j++,k++)  //-er[i]+1
 92             if (b[ f[j][i-1] ] < b[ f[k][i-1] ])
 93                 f[j][i]=f[j][i-1];
 94             else
 95                 f[j][i]=f[k][i-1];
 96 //            f[j][i]=min(f[j][i-1],f[j+er[i-1]][i-1]);
 97
 98     while (q--)
 99     {
100         scanf("%d%d",&x,&y);
101         x=lef[x];
102         y=lef[y];
103         if (x>y)
104             swap(x,y);
105         d=log(y-x+1)/log(2);
106         j=y-er[d]+1;
107         if (b[ f[x][d] ] < b[ f[j][d] ])    //+1
108             printf("%d\n",a[ f[x][d] ]);
109         else
110             printf("%d\n",a[ f[j][d] ]);
111 //        printf("%d\n",min(f[x][d],f[y-er[d]+1][d]));
112     }
113     return 0;
114 }
115 /*
116 8 100 1
117 1 2
118 1 3
119 2 4
120 2 5
121 3 6
122 5 7
123 6 8
124
125 5 7
126 5
127 2 3
128 1
129 3 2
130 1
131 1 8
132 1
133 2 8
134 1
135 4 5
136 2
137 5 4
138 2
139 */

2.欧拉序+线段树

  1 /*
  2 在这里,对于一个数,选择最左边的
  3 选择任意一个都可以,[left_index,right_index],深度都大于等于这个数的深度
  4 */
  5 #include <cstdio>
  6 #include <cstdlib>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <time.h>
 10 #include <string>
 11 #include <set>
 12 #include <map>
 13 #include <list>
 14 #include <stack>
 15 #include <queue>
 16 #include <vector>
 17 #include <bitset>
 18 #include <ext/rope>
 19 #include <algorithm>
 20 #include <iostream>
 21 using namespace std;
 22 #define ll long long
 23 #define minv 1e-6
 24 #define inf 1e9
 25 #define pi 3.1415926536
 26 #define E  2.7182818284
 27 const ll mod=1e9+7;//998244353
 28 const int maxn=5e5+10;
 29
 30 struct node
 31 {
 32     int d;
 33     node *next;
 34 }*e[maxn];
 35
 36 int s=0;
 37
 38 ///每条边走两遍,n-1条边,走2(n-1)个点
 39 int a[maxn<<1],b[maxn<<1],lef[maxn],f[maxn<<3];
 40 bool vis[maxn]={0};
 41 int num=0;
 42
 43 void dfs(int d,int dep)
 44 {
 45     node* p=e[d];
 46     vis[d]=1;
 47     s++;
 48     lef[d]=s;
 49     a[s]=d;
 50     b[s]=dep;
 51     while (p)
 52     {
 53         if (!vis[p->d])
 54         {
 55             dfs(p->d,dep+1);
 56             s++;
 57             a[s]=d;
 58             b[s]=dep;
 59         }
 60         p=p->next;
 61     }
 62 }
 63
 64 void build(int index,int l,int r)
 65 {
 66     if (l==r)
 67         f[index]=++num;
 68     else
 69     {
 70         int m=(l+r)>>1;
 71         build(index<<1,l,m);
 72         build(index<<1|1,m+1,r);
 73         if (b[f[index<<1]]<b[f[index<<1|1]])
 74             f[index]=f[index<<1];
 75         else
 76             f[index]=f[index<<1|1];
 77     }
 78 }
 79
 80 int query(int index,int l,int r,int x,int y)
 81 {
 82     if (x<=l && r<=y)
 83         return f[index];
 84     if (r<x || l>y)
 85         return 0;
 86     int m=(l+r)>>1;
 87     int p=query(index<<1,l,m,x,y);
 88     int q=query(index<<1|1,m+1,r,x,y);
 89     if (b[p]<b[q])
 90         return p;
 91     else
 92         return q;
 93 }
 94
 95 int main()
 96 {
 97     int n,q,root,x,y,i,j,m,d;
 98     node *p;
 99     scanf("%d%d%d",&n,&q,&root);
100     for (i=1;i<n;i++)
101     {
102         scanf("%d%d",&x,&y);
103         p=(node*) malloc (sizeof(node));
104         p->d=y;
105         p->next=e[x];
106         e[x]=p;
107
108         p=(node*) malloc (sizeof(node));
109         p->d=x;
110         p->next=e[y];
111         e[y]=p;
112     }
113     dfs(root,1);
114
115     b[0]=n+1;
116     build(1,1,s);
117     while (q--)
118     {
119         scanf("%d%d",&x,&y);
120         x=lef[x];
121         y=lef[y];
122         if (x>y)
123             swap(x,y);
124         printf("%d\n",a[query(1,1,s,x,y)]);
125     }
126     return 0;
127 }

3.离线dfs

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <time.h>
  6 #include <string>
  7 #include <set>
  8 #include <map>
  9 #include <list>
 10 #include <stack>
 11 #include <queue>
 12 #include <vector>
 13 #include <bitset>
 14 #include <ext/rope>
 15 #include <algorithm>
 16 #include <iostream>
 17 using namespace std;
 18 #define ll long long
 19 #define minv 1e-6
 20 #define inf 1e9
 21 #define pi 3.1415926536
 22 #define E  2.7182818284
 23 const ll mod=1e9+7;//998244353
 24 const int maxn=5e5+10;
 25
 26 struct node
 27 {
 28     int d;
 29     node *next;
 30 }*e[maxn];
 31 struct rec
 32 {
 33     int d,index;
 34     rec *next;
 35 }*ask[maxn];
 36 bool vis[maxn]={0};
 37
 38 int r[maxn],fa[maxn];
 39
 40 int getfather(int d)
 41 {
 42     if (fa[d]==d)
 43         return d;
 44     fa[d]=getfather(fa[d]);
 45     return fa[d];
 46 }
 47
 48 void merge(int x,int y)
 49 {
 50     int s=getfather(x);
 51     int t=getfather(y);
 52     fa[t]=s;
 53 }
 54
 55 void dfs(int d)
 56 {
 57     node *p;
 58     rec *v;
 59     vis[d]=1;
 60
 61     p=e[d];
 62     while (p)
 63     {
 64         if (!vis[p->d])
 65         {
 66             dfs(p->d);
 67             merge(d,p->d);
 68         }
 69         p=p->next;
 70     }
 71
 72     v=ask[d];
 73     while (v)
 74     {
 75         if (vis[v->d])
 76             r[v->index]=getfather(v->d);
 77         v=v->next;
 78     }
 79 }
 80
 81 int main()
 82 {
 83     node *p;
 84     rec *v;
 85     int n,q,root,x,y,i;
 86     scanf("%d%d%d",&n,&q,&root);
 87     for (i=1;i<n;i++)
 88     {
 89         scanf("%d%d",&x,&y);
 90         p=(node*) malloc (sizeof(node));
 91         p->d=y;
 92         p->next=e[x];
 93         e[x]=p;
 94
 95         p=(node*) malloc (sizeof(node));
 96         p->d=x;
 97         p->next=e[y];
 98         e[y]=p;
 99     }
100
101     for (i=1;i<=q;i++)
102     {
103         scanf("%d%d",&x,&y);
104         v=(rec*) malloc (sizeof(rec));
105         v->d=y;
106         v->index=i;
107         v->next=ask[x];
108         ask[x]=v;
109
110         v=(rec*) malloc (sizeof(rec));
111         v->d=x;
112         v->index=i;
113         v->next=ask[y];
114         ask[y]=v;
115     }
116
117     for (i=1;i<=n;i++)
118         fa[i]=i;
119     dfs(root);
120     for (i=1;i<=q;i++)
121         printf("%d\n",r[i]);
122     return 0;
123 }

原文地址:https://www.cnblogs.com/cmyg/p/9545267.html

时间: 2024-08-04 11:30:55

lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs的相关文章

BZOJ 3779 重组病毒 LCT+线段树维护DFS序

题目大意:给定一棵树,初始每个点都有一个颜色,支持三种操作: 1.将某个点到根的路径上所有点染上一种新的颜色 2.将某个点到根的路径上所有点染上一种新的颜色,然后把根设为这个点 3.定义一个点的代价为这个点到根路径上颜色的种类数,求某个点子树中所有点代价的平均值 我真是炖了狗了-- 容易发现这玩应就是个LCT,操作1就是Access,操作2就是Move_To_Root,代价就是一个点到根路径上的虚边数量+1 我们用LCT模拟上述操作,用线段树维护DFS序维护信息,一旦LCT中出现了虚实边的切换,

CF877E Danil and a Part-time Job 线段树维护dfs序

\(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 pow 将一个点 x 的子树中所有节点取反 对于每个 get 给出答案 \(\color{#0066ff}{输入格式}\) 第一行一个整数 n 第二行共 n?1 个整数,第 i 个数 \(x_i\) 表示 \(x_i\) 是 i+1 的父亲, 第三行给出每个点的初始权值 第四行一个整数 m 接下来

Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 else 区间覆盖 push_up的时候要注意好多细节,, 数组尽量往大开 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const in

CodeForces 343D 线段树维护dfs序

给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u], 访问结点u的时间戳,out[u],离开结点u的时间戳 每个结点的in值对应在线段树中的区间的一点 那么对于操作1, 只要将区间[in[u],out[u]] 的值都改为1, 但是如果区间[in[u],out[u]] 原先存在为0的点,那么父区间肯定是空的,这个操作不能 改变父区间的状态,所以需要

BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题,是时候复习一波离线算法泡脑子了.(没有暴力分的题,想不出来正解就爆零,太可怕了) 排序后离线操作通过前缀和计算答案,题解是hzwer的博客上复制的 http://hzwer.com/3891.html 直接引用清华爷gconeice的题解吧 显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力

poj 3264 Balanced Lineup RMQ线段树实现

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36613   Accepted: 17141 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

【BZOJ-3306】树 线段树 + DFS序

3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] Description 给定一棵大小为 n 的有根点权树,支持以下操作: • 换根 • 修改点权      • 查询子树最小值 Input 第一行两个整数 n, Q ,分别表示树的大小和操作数. 接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权.保证f < i.如 果f = 0

CodeForces 838B - Diverging Directions - [DFS序+线段树]

题目链接:http://codeforces.com/problemset/problem/838/B You are given a directed weighted graph with n nodes and 2n?-?2 edges. The nodes are labeled from 1 to n, while the edges are labeled from 1 to 2n?-?2. The graph's edges can be split into two parts.

HDU5692(线段树+dfs序)

Snacks Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求