zoukankan      html  css  js  c++  java
  • 「BZOJ3123」[SDOI2013]森林

    用主席树记录每个节点到根节点的信息,用树上差分的思想查询。

    合并时把节点数小的合并到节点数大的上,也就是启发式合并,

    合并时重建小树上的主席树。

      1 #include<cstdio>
      2 #include<vector>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=80010,M=N*128,P=20;
      6 int n,m,q,maxp,a[N],rank[N],pos[N];
      7 int fa[N][P],dep[N],siz[N];
      8 int root[N],treeroot[N];
      9 int tot,lc[M],rc[M],sum[M];
     10 vector<int>g[N];
     11 int cmp(const int x,const int y){return a[x]<a[y];}
     12 inline int read(){
     13     int x=0,w=1;char c=0;
     14     while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
     15     while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
     16     return x*w;
     17 }
     18 void insert(int& k,int l,int r,int v){
     19     tot++;
     20     lc[tot]=lc[k],rc[tot]=rc[k],sum[tot]=sum[k]+1;
     21     k=tot;
     22     if(l==r) return;
     23     int mid=(l+r)>>1;
     24     if(v<=mid) insert(lc[k],l,mid,v);
     25     else insert(rc[k],mid+1,r,v);
     26     return;
     27 }
     28 int que(int now1,int now2,int pre1,int pre2,int l,int r,int k){
     29     if(l==r) return l;
     30     int mid=(l+r)>>1;
     31     int lsum=sum[lc[now1]]+sum[lc[now2]]-sum[lc[pre1]]-sum[lc[pre2]];
     32     if(lsum>=k) return que(lc[now1],lc[now2],lc[pre1],lc[pre2],l,mid,k);
     33     else return que(rc[now1],rc[now2],rc[pre1],rc[pre2],mid+1,r,k-lsum);
     34 }
     35 void dfs(int k,int father,int d,int r){ //dfs同时建立主席树
     36     treeroot[k]=r,fa[k][0]=father,dep[k]=d,siz[k]=1;
     37     int x;
     38     for(int i=1;i<=17;i++) fa[k][i]=fa[fa[k][i-1]][i-1];
     39     for(int i=0;i<g[k].size();i++){
     40         x=g[k][i];
     41         if(x==father) continue;
     42         root[x]=root[k];
     43         insert(root[x],1,n,rank[x]);
     44         dfs(x,k,d+1,r);
     45         siz[k]+=siz[x];
     46     }
     47     return;
     48 }
     49 int getlca(int x,int y){
     50     if(dep[x]<dep[y]) swap(x,y);
     51     for(int i=17;i>=0;i--)
     52         if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
     53     if(x==y) return x;
     54     for(int i=17;i>=0;i--)
     55         if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
     56     return fa[x][0];
     57 }
     58 void marge(int s,int t){
     59     if(siz[treeroot[s]]<siz[treeroot[t]]) swap(s,t);
     60     root[t]=root[s];
     61     insert(root[t],1,n,rank[t]);
     62     dfs(t,s,dep[s]+1,treeroot[s]);
     63     return;
     64 }
     65 void reset(){
     66     tot=0;
     67     for(int i=1;i<=n;i++) g[i].clear();
     68     return;
     69 }
     70 void solve(){
     71     char opt[10];
     72     int t1,t2,t3;
     73     n=read(),m=read(),q=read();
     74     for(int i=1;i<=n;i++) a[i]=read(),pos[i]=i;
     75     sort(pos+1,pos+n+1,cmp);
     76     for(int i=1;i<=n;i++) rank[pos[i]]=i;
     77     for(int i=1;i<=m;i++){t1=read(),t2=read();g[t1].push_back(t2);g[t2].push_back(t1);}
     78     for(int i=1;i<=n;i++) if(!dep[i]){
     79         root[i]=0;
     80         insert(root[i],1,n,rank[i]);
     81         dfs(i,0,1,i);
     82     }
     83     int lastans=0;
     84     while(q--){
     85         scanf("%s",opt);
     86         t1=read(),t2=read();
     87         if(opt[0]=='Q'){
     88             t3=read();
     89             t1^=lastans,t2^=lastans,t3^=lastans;
     90             int lca=getlca(t1,t2);
     91             lastans=a[pos[que(root[t1],root[t2],root[lca],root[fa[lca][0]],1,n,t3)]];
     92             printf("%d
    ",lastans);
     93         }else{
     94             t1^=lastans,t2^=lastans;
     95             g[t1].push_back(t2);g[t2].push_back(t1);
     96             marge(t1,t2);
     97         }
     98     }
     99     reset();
    100     return;
    101 }
    102 int main(){
    103     int T;
    104     while(scanf("%d",&T)!=EOF) solve();
    105     return 0;
    106 }
  • 相关阅读:
    代表行为已成为习惯的信号有哪些?
    Java使用JDBC连接Oracle数据库
    JS正则表达式
    java实现内网通信
    纯前端代码实现美团外卖页面
    HTML绘制表格
    教你如何使用谷歌浏览器,亲测可用!
    Java 多线程实现多窗口同时售票简单功能
    实现获取命令行的返回结果
    HTML模仿实现京东登录页面
  • 原文地址:https://www.cnblogs.com/mycups/p/8554746.html
Copyright © 2011-2022 走看看