ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Luogu 3302 森林(树上维护主席树)

2021-09-20 23:05:40  阅读:156  来源: 互联网

标签:ch return int Luogu sum deep 树上 3302 fo


P3302 [SDOI2013]森林 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)P3302 [SDOI2013]森林 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

大概就是要在树上搞第k小吗,还要支持合并

讲实话第一反应树剖+线段树维护,然后就傻掉了

讲正解:
每一个节点开一颗主席树维护从该节点到根节点的路径信息

然后x->y的路径就很明显要用到LCA

至于第二问,我们采用启发式合并,复杂度好像可以均摊到logn,每次将小的向大的合并。

//code by SPzos
#include<bits/stdc++.h>
#define fo(i,j,k) for(register int i=j;i<=k;++i)
using namespace std;
const int N=8e4+5;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){ if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;    
}
struct edge{
    int v,nxt;
}e[N<<2];
int cnt,head[N<<2],n,m,T,a[N],b[N],col[N],lg[N]; 
inline void add(int x,int y){
    e[++cnt].nxt=head[x];
    e[cnt].v=y;
    head[x]=cnt;
} 
struct node{
    int l,r,sum;
}t[N*105];
int top,f[N][35],deep[N],size[N],root[N],tot,kk;
void build(int &pos,int pre,int l,int r,int wi){
    t[pos=++top]=t[pre];
    t[pos].sum++;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(wi<=mid) build(t[pos].l,t[pre].l,l,mid,wi);
    else build(t[pos].r,t[pre].r,mid+1,r,wi);
    return;
}

void dfs(int u,int fa,int rt){
    build(root[u],root[fa],1,tot,a[u]);
    deep[u]=deep[fa]+1;f[u][0]=fa;
    size[rt]++;col[u]=rt;
    for(int i=1;i<=18;i++)
        f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].nxt)
        if(e[i].v!=fa) dfs(e[i].v,u,rt);
    return;
}
int lca(int u,int v){
    if(deep[u]<deep[v]) swap(u,v);
    while(deep[u]>deep[v]) u=f[u][lg[deep[u]-deep[v]]];
    if(u==v) return u;
    for(int i=lg[deep[u]];i>=0;i--)
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];
    return f[u][0]; 
}
int Answer(int u,int v,int og,int fg,int l,int r,int k){
    if(l==r) return b[l];
    int sum=t[t[u].l].sum+t[t[v].l].sum-t[t[og].l].sum-t[t[fg].l].sum;
    int mid=(l+r)>>1;
    if(k<=sum) return Answer(t[u].l,t[v].l,t[og].l,t[fg].l,l,mid,k);
    return Answer(t[u].r,t[v].r,t[og].r,t[fg].r,mid+1,r,k-sum);    
}
void work(){
    lg[0]=-1;
    T=read();    n=read();m=read();kk=read();
        fo(i,1,n) b[i]=a[i]=read(),lg[i]=lg[i>>1]+1,col[i]=i;
        sort(b+1,b+1+n);
        tot=unique(b+1,b+1+n)-b-1;
        fo(i,1,n){
            a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
        }
        fo(i,1,m){
            int x=read(),y=read();
            add(x,y);
            add(y,x);
        }
}
int main(){
    work();
        fo(i,1,n){
        if(col[i]==i) dfs(i,0,i); 
        }
        int last=0;
        char ch[5];
        int x,y,k;
        for(int i=1;i<=kk;i++){
        scanf("%s",ch);x=read()^last;y=read()^last;
        if(ch[0]=='Q'){
            k=read()^last;
            int og=lca(x,y),fg=f[og][0];
            last=Answer(root[x],root[y],root[og],root[fg],1,tot,k);
            printf("%d\n",last);        
        }
        else{
            add(x,y);add(y,x);
            int fx=col[x],fy=col[y];
            if(size[fy]<size[fx]) dfs(y,x,fx);
            else dfs(x,y,fy);
        }
    }
    return 0;
} 

 

标签:ch,return,int,Luogu,sum,deep,树上,3302,fo
来源: https://www.cnblogs.com/simpleton/p/15315615.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有