zoukankan      html  css  js  c++  java
  • [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)

    传送门

    突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288

    首先有两个操作,一个查询,一个连接

    查询的话,直接在树上建主席树

    然后难点在于连接

    用启发式合并就可以了(想了半天都没想出来)

    每次合并时,我们把小的树接到大的上,然后dfs一遍小的树,更新信息

    然后注意数组……别太小也别太大……(被数组大小坑了好几次提交)

      1 //minamoto
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      5 char buf[1<<21],*p1=buf,*p2=buf;
      6 inline int read(){
      7     #define num ch-'0'
      8     char ch;bool flag=0;int res;
      9     while(!isdigit(ch=getc()))
     10     (ch=='-')&&(flag=true);
     11     for(res=num;isdigit(ch=getc());res=res*10+num);
     12     (flag)&&(res=-res);
     13     #undef num
     14     return res;
     15 }
     16 char obuf[1<<24],*o=obuf;
     17 void print(int x){
     18     if(x>9) print(x/10);
     19     *o++=x%10+48;
     20 }
     21 const int N=80005,M=N*200;
     22 int ver[N<<2],Next[N<<2],head[N];
     23 int a[N],fa[N],sz[N],b[N];
     24 int n,m,tot,q,size,ans;
     25 void add(int u,int v){
     26     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     27     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
     28 }
     29 int L[M],R[M],sum[M],rt[N],cnt;
     30 void update(int last,int &now,int l,int r,int x){
     31     sum[now=++cnt]=sum[last]+1;
     32     if(l==r) return;
     33     int mid=(l+r)>>1;
     34     if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
     35     else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
     36 }
     37 int query(int u,int v,int lca,int lca_fa,int l,int r,int k){
     38     if(l>=r) return l;
     39     int x=sum[L[v]]+sum[L[u]]-sum[L[lca]]-sum[L[lca_fa]];
     40     int mid=(l+r)>>1;
     41     if(x>=k) return query(L[u],L[v],L[lca],L[lca_fa],l,mid,k);
     42     else return query(R[u],R[v],R[lca],R[lca_fa],mid+1,r,k-x);
     43 }
     44 inline int hash(int x){
     45     return lower_bound(b+1,b+1+size,x)-b;
     46 }
     47 int ff(int x){
     48     return fa[x]==x?x:fa[x]=ff(fa[x]);
     49 }
     50 int st[N][17],d[N],vis[N];
     51 void dfs(int u,int father,int root){
     52     st[u][0]=father;
     53     for(int i=1;i<=16;++i)
     54     st[u][i]=st[st[u][i-1]][i-1];
     55     ++sz[root];
     56     d[u]=d[father]+1;
     57     fa[u]=root;
     58     vis[u]=1;
     59     update(rt[father],rt[u],1,size,hash(a[u]));
     60     for(int i=head[u];i;i=Next[i]){
     61         int v=ver[i];
     62         if(v==father) continue;
     63         dfs(v,u,root);
     64     }
     65 }
     66 int LCA(int x,int y){
     67     if(x==y) return x;
     68     if(d[x]<d[y]) swap(x,y);
     69     for(int i=16;i>=0;--i){
     70         if(d[st[x][i]]>=d[y]) x=st[x][i];
     71     }
     72     if(x==y) return x;
     73     for(int i=16;i>=0;--i){
     74         if(st[x][i]!=st[y][i])
     75         x=st[x][i],y=st[y][i];
     76     }
     77     return st[x][0];
     78 }
     79 int main(){
     80     //freopen("testdata.in","r",stdin);
     81     int t=read();
     82     n=read(),m=read(),q=read();
     83     for(int i=1;i<=n;++i)
     84     a[i]=b[i]=read(),fa[i]=i;
     85     sort(b+1,b+1+n);
     86     size=unique(b+1,b+1+n)-b-1;
     87     for(int i=1;i<=m;++i){
     88         int u=read(),v=read();
     89         add(u,v);
     90     }
     91     for(int i=1;i<=n;++i)
     92     if(!vis[i]) dfs(i,0,i);
     93     while(q--){
     94         char ch;int x,y;
     95         while(!isupper(ch=getc()));
     96         x=read()^ans,y=read()^ans;
     97         if(ch=='Q'){
     98             int k=read()^ans;
     99             int lca=LCA(x,y);
    100             ans=b[query(rt[x],rt[y],rt[lca],rt[st[lca][0]],1,size,k)];
    101             print(ans),*o++='
    ';
    102         }
    103         else{
    104             add(x,y);
    105             int u=ff(x),v=ff(y);
    106             if(sz[u]<sz[v]) swap(x,y),swap(u,v);
    107             dfs(y,x,u);
    108         }
    109     }
    110     fwrite(obuf,o-obuf,1,stdout);
    111     return 0;
    112 }
  • 相关阅读:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    14.18 InnoDB Backup and Recovery 备份和恢复:
    php使用 _before_index() 来实现访问页面前,判断登录
    php使用 _before_index() 来实现访问页面前,判断登录
    查询方式实例演示
    查询方式实例演示
    haproxy timeout server 46000 后台超时时间
    haproxy timeout server 46000 后台超时时间
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9396807.html
Copyright © 2011-2022 走看看