• BZOJ 3123 SDOI2013 森林 启发式合并+主席树


    题意:

      给出一个森林,强制在线,支持动态加边和询问链上第k大,保证加边后图仍然是森林。

    分析:

      有一点经验的选手都清楚,动态加边想LCT,第K大想主席树,于是有大爷LCT+主席树秒了%%%(我并不会)

      观察问题,出题人在这里摆下了一个疑阵,故意引我们向link-cut tree上去思考,但是,我们发现,这个招数未免太过手下留情,如果出题人想要让我们非用LCT不可呢,不妨加一个删边操作,可是没有,所以我们判断这里多半有诈!

      加边操作,可以看作是合并连通块信息,所以我们可以想到启发式合并(在合并的过程中重构倍增lca数组,修改主席树),对于询问,我们可以用主席树处理。

      这道题需要对启发式合并,LCA,主席树算法的灵活运用,不失为一道数据结构好题。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ms(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 const int N=1000005,inf=1e9;
     5 struct node{int y,nxt;}e[N*2];
     6 int o,n,m,ans=0,c=1,cnt=0,rt[N],ls[N*5],rs[N*5];
     7 int siz[N*5],sm[N],f[N],nm[N],fa[N][20],d[N],t;
     8 int h[N];bool vis[N];char s[10];
     9 int get(int x){
    10     return f[x]==x?x:f[x]=get(f[x]);
    11 } void add(int x,int y){
    12     e[++c]=(node){y,h[x]};h[x]=c;
    13     e[++c]=(node){x,h[y]};h[y]=c;
    14 } int lca(int x,int y){
    15     if(d[x]<d[y]) swap(x,y);
    16     int l=d[x]-d[y];
    17     for(int i=19;~i;i--)
    18     if((1<<i)&l) x=fa[x][i];
    19     if(x==y) return x;
    20     for(int i=19;~i;i--)
    21     if(fa[x][i]!=fa[y][i])
    22     x=fa[x][i],y=fa[y][i];
    23     return fa[x][0];
    24 } void update(int x,int &nw,int l,int r,int v){
    25     if(!nw) nw=++cnt;siz[nw]=siz[x]+1;
    26     if(l==r) return ;int mid=l+r>>1;
    27     if(v<=mid) rs[nw]=rs[x],
    28     update(ls[x],ls[nw],l,mid,v);
    29     else ls[nw]=ls[x],
    30     update(rs[x],rs[nw],mid+1,r,v);return ;
    31 } int query(int x,int y,int u,int v,int l,int r,int w){
    32     if(l==r) return l;int mid=l+r>>1,re;
    33     re=siz[ls[x]]+siz[ls[y]]-siz[ls[u]]-siz[ls[v]];
    34     if(w<=re) return 
    35     query(ls[x],ls[y],ls[u],ls[v],l,mid,w);
    36     else return 
    37     query(rs[x],rs[y],rs[u],rs[v],mid+1,r,w-re);
    38 } void dfs(int x,int f){
    39     vis[x]=1;d[x]=d[f]+1;fa[x][0]=f;
    40     for(int i=1;i<=19;i++)
    41     fa[x][i]=fa[fa[x][i-1]][i-1];
    42     update(rt[f],rt[x],0,inf,nm[x]);
    43     for(int i=h[x],y;~i;i=e[i].nxt)
    44     if((y=e[i].y)!=f) dfs(y,x);
    45 } void merge(int x,int y){
    46     int fx=get(x),fy=get(y);
    47     f[fx]=fy;sm[fy]+=sm[fx];
    48 } int main(){
    49     ms(h,-1);ms(vis,0);ms(rt,0);
    50     scanf("%d%d%d%d",&o,&n,&m,&t);
    51     for(int i=1;i<=n;i++)
    52     scanf("%d",&nm[i]),f[i]=i,sm[i]=1;
    53     for(int i=1,x,y;i<=m;i++)
    54     scanf("%d%d",&x,&y),add(x,y),merge(x,y);
    55     for(int i=1;i<=n;i++)
    56     if(!vis[i]) dfs(i,0);
    57     for(int i=1,x,y,z;i<=t;i++){
    58         scanf("%s",s);
    59         if(s[0]=='Q'){
    60             scanf("%d%d%d",&x,&y,&z);
    61             x^=ans;y^=ans;z^=ans;
    62             int nw=lca(x,y);ans=
    63             query(rt[x],rt[y],rt[nw],rt[fa[nw][0]],
    64             0,inf,z);printf("%d
    ",ans);
    65         } else{
    66             scanf("%d%d",&x,&y);
    67             x^=ans;y^=ans;
    68             int fx=get(x),fy=get(y);
    69             if(sm[fx]>sm[fy]) swap(y,x);
    70             add(x,y);merge(x,y);dfs(x,y);
    71         }
    72     } return 0;
    73 }
    主席树
  • 相关阅读:
    cJSON获取bool值
    电视节目rtmp流
    huggingface. doc
    Huggingface🤗NLP笔记3:Pipeline端到端的背后发生了什么
    nemo代码
    《Huggingface Transformers实战教程 》
    LIC2021 DuIE 关系抽取基线
    PaddleNLP实战——信息抽取(InfoExtraction)
    NVIDIA NeMo:一个开源工具包,可通过三行代码开发最先进的会话式AI模型
    开发一个会说中文的问答机器人需要几步?英伟达技术专家教你上手
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10391895.html
Copyright © 2020-2023  润新知