luogu2633 Count on a tree(树上LCA+主席树求区间第k小)

传送:

https://www.luogu.org/problem/P2633

题意:

给定一棵$N$个节点的树,每个点有一个权值,对于$M$个询问$(u,v,k)$,你需要回答$u xor lastans$和$v$这两个节点间第$K$小的点权。其中$lastans$是上一个询问的答案,初始为0,即第一个询问的u是明文。

数据范围:

$1<=n,m<=1e5$。

分析:

一维状态下的求区间第k小,用主席树维护,$n$棵树代表$n$个下标(位置),那么对于树上的结构怎么表示先后关系呢?

很容易想到父亲与儿子,那么可以建立$n$棵树,儿子的树是在父亲的树的基础上建立的。因为从根节点出发,一定会经过父亲到达某个点。

对于$u$到$v$的路径上的答案,可以表示为:

$num[u]-num[lca(u,v)]+num[v]-num[lca(u,v)]+num[lca(u,v)]-num[lca(lca(u,v))]$

$=num[u]+num[v]-num[lca(u,v)]-num[lca(lca(u,v))]$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 struct node{
 5     int to,nxt;
 6 }edge[maxn*2];
 7 struct node2{
 8     int l,r,num;
 9 }tree[maxn*70];
10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn];
11 void add(int x,int y){
12     edge[++num]={y,head[x]};head[x]=num;
13 }
14 void update(int &x,int y,int l,int r,int dex){
15     x=++size;tree[x]=tree[y];tree[x].num++;
16     if (l==r) return ;
17     int mid=(l+r)>>1;
18     if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex);
19     else update(tree[x].r,tree[y].r,mid+1,r,dex);
20 }
21 int LCA(int x,int y){
22     if (deep[x]>deep[y]) swap(x,y);
23     for (int j=N;j>=0;j--)
24         if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j];
25     if (x==y) return x;
26     for (int j=N;j>=0;j--)
27         if (fa[x][j]!=fa[y][j]){
28             x=fa[x][j];y=fa[y][j];
29         }
30     return fa[x][0];
31 }
32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){
33     if (l==r) return l;
34     int mid=(l+r)>>1;
35     int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num;
36     if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk);
37     else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp);
38 }
39 void dfs(int x,int faa){
40     int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl;
41     update(root[x],root[faa],1,tot,dex);
42     fa[x][0]=faa; deep[x]=deep[faa]+1;
43     for (int i=1;(1<<i)<=deep[x];i++)
44         fa[x][i]=fa[fa[x][i-1]][i-1];
45     for (int i=head[x];i!=-1;i=edge[i].nxt){
46         int tmp=edge[i].to;
47         if (tmp==faa) continue;
48         dfs(tmp,x);
49     } 
50 }
51 void init(int n){
52     for (int i=0;i<=n;i++) head[i]=-1;
53     num=0;size=0;deep[0]=0;
54     N=floor(log(1.0*n)/log(2.0));
55 }
56 int main(){
57     int n,m,x,y,k;scanf("%d%d",&n,&m);
58     init(n);
59     for (int i=1;i<=n;i++){
60         scanf("%d",&a[i]);
61         refl[i]=a[i];
62     }
63     sort(refl+1,refl+1+n);
64     tot=unique(refl+1,refl+1+n)-(refl+1);
65     for (int i=1;i<=n-1;i++){
66         scanf("%d%d",&x,&y);
67         add(x,y); add(y,x);
68     }
69     dfs(1,0);
70     int Lans=0;
71     while(m--){
72         scanf("%d%d%d",&x,&y,&k);
73         x^=Lans; int _lca=LCA(x,y);
74         int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k);
75         printf("%d\n",Lans=refl[tmp]);
76     } 
77     return 0;
78 }
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 struct node{
 5     int to,nxt;
 6 }edge[maxn*2];
 7 struct node2{
 8     int l,r,num;
 9 }tree[maxn*70];
10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn];
11 void add(int x,int y){
12     edge[++num]={y,head[x]};head[x]=num;
13 }
14 void update(int &x,int y,int l,int r,int dex){
15     x=++size;tree[x]=tree[y];tree[x].num++;
16     if (l==r) return ;
17     int mid=(l+r)>>1;
18     if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex);
19     else update(tree[x].r,tree[y].r,mid+1,r,dex);
20 }
21 int LCA(int x,int y){
22     if (deep[x]>deep[y]) swap(x,y);
23     for (int j=N;j>=0;j--)
24         if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j];
25     if (x==y) return x;
26     for (int j=N;j>=0;j--)
27         if (fa[x][j]!=fa[y][j]){
28             x=fa[x][j];y=fa[y][j];
29         }
30     return fa[x][0];
31 }
32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){
33     if (l==r) return l;
34     int mid=(l+r)>>1;
35     int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num;
36     if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk);
37     else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp);
38 }
39 void dfs(int x,int faa){
40     int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl;
41     update(root[x],root[faa],1,tot,dex);
42     fa[x][0]=faa; deep[x]=deep[faa]+1;
43     for (int i=1;(1<<i)<=deep[x];i++)
44         fa[x][i]=fa[fa[x][i-1]][i-1];
45     for (int i=head[x];i!=-1;i=edge[i].nxt){
46         int tmp=edge[i].to;
47         if (tmp==faa) continue;
48         dfs(tmp,x);
49     } 
50 }
51 void init(int n){
52     for (int i=0;i<=n;i++) head[i]=-1;
53     num=0;size=0;deep[0]=0;
54     N=floor(log(1.0*n)/log(2.0));
55 }
56 int main(){
57     int n,m,x,y,k;scanf("%d%d",&n,&m);
58     init(n);
59     for (int i=1;i<=n;i++){
60         scanf("%d",&a[i]);
61         refl[i]=a[i];
62     }
63     sort(refl+1,refl+1+n);
64     tot=unique(refl+1,refl+1+n)-(refl+1);
65     for (int i=1;i<=n-1;i++){
66         scanf("%d%d",&x,&y);
67         add(x,y); add(y,x);
68     }
69     dfs(1,0);
70     int Lans=0;
71     while(m--){
72         scanf("%d%d%d",&x,&y,&k);
73         x^=Lans; int _lca=LCA(x,y);
74         int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k);
75         printf("%d\n",Lans=refl[tmp]);
76     } 
77     return 0;
78 }

PS。bzoj2588卡内存,主席树开*70就过了。

 

posted @ 2019-08-28 14:28  Changer-qyz  阅读(202)  评论(0编辑  收藏  举报