zoukankan      html  css  js  c++  java
  • 可持久化线段树

    bzoj 3123 森林

    一开始图是森林 考虑树上两个节点间查询路径上k 大值 可维护两个节点到这棵树上根节点的权值线段树 这里可以使用可持久化思想 利用每一个点的父亲来维护这个点上的权值线段树

            那么两者路径上的权值线段树 即 Tree[x]+Tree[y]-Tree[lca(x,y)]-Tree[fa[lca(x,y)]];       所以询问的复杂度为 O(MlogN) 

            考虑合并  可使用启发式合并 。。很强 很暴力 合并复杂度 为 O(Nlog2N)

      1 #include <bits/stdc++.h>
      2 #define N 80010
      3 #define M 26001000
      4 using namespace std;
      5 int T,siz,n,m,q,st[N],root[N],x,y,z;
      6 int a[N],val[N],ee,vt;
      7 struct node{
      8     int u,v,next;
      9 }vs[N<<1];
     10 void vsadd(int u,int v)
     11 {
     12     vs[ee].u=u,vs[ee].v=v;
     13     vs[ee].next=st[u];st[u]=ee++;
     14 }
     15 struct Seg
     16 {
     17     int l,r,sum;
     18 }seg[M];
     19 void pushup(int rt)
     20 {
     21     seg[rt].sum=seg[seg[rt].l].sum+seg[seg[rt].r].sum;
     22 }
     23 void insert(int x,int &y,int l,int r,int v)
     24 {
     25     y=++siz;seg[y]=seg[x];seg[y].sum++;
     26     if(l==r) return;int mid=(l+r)>>1;
     27     if(v<=mid) insert(seg[x].l,seg[y].l,l,mid,v);
     28     else insert(seg[x].r,seg[y].r,mid+1,r,v);
     29     pushup(y);
     30 }
     31 int query(int a,int b,int c,int d,int l,int r,int kth)
     32 {
     33     if(l==r) return l;int mid=(l+r)>>1;
     34     int tmp=seg[seg[a].l].sum+seg[seg[b].l].sum-seg[seg[c].l].sum-seg[seg[d].l].sum;
     35     if(tmp<kth) return query(seg[a].r,seg[b].r,seg[c].r,seg[d].r,mid+1,r,kth-tmp);
     36     else return query(seg[a].l,seg[b].l,seg[c].l,seg[d].l,l,mid,kth);
     37 }
     38 int dvsp[N],fa[N][25],ffa[N],size[N],sta[N],vp;
     39 int find(int x)
     40 {
     41     if(x==ffa[x]) return x;
     42     return ffa[x]=find(ffa[x]);
     43 }
     44 void dfs(int now,int ff)
     45 {
     46     insert(root[ff],root[now],1,vt,val[now]);
     47     dvsp[now]=dvsp[ff]+1,fa[now][0]=ff;
     48     for(int i=st[now];i!=-1;i=vs[i].next)
     49     {
     50         int v=vs[i].v;
     51         if(v==ff) continue;
     52         dfs(v,now);int fv=find(v),fnow=find(now);
     53         if(size[fv]<size[fnow])
     54             ffa[fnow]=fv,size[fv]+=size[fnow];
     55         else ffa[fv]=fnow,size[fnow]+=size[fv];
     56     }
     57 }
     58 int lca(int x,int y)
     59 {
     60     if(dvsp[x]<dvsp[y])swap(x,y);
     61     for(int i=20;i>=0;i--) if(dvsp[fa[x][i]]>=dvsp[y])x=fa[x][i];
     62     if(x==y)return x;
     63     for(int i=20;i>=0;i--) if(dvsp[fa[x][i]]==dvsp[fa[y][i]]&&fa[x][i]!=fa[y][i])
     64             x=fa[x][i],y=fa[y][i];
     65     return fa[x][0];
     66 }
     67 void Rebuild(int x,int ff)
     68 {
     69     sta[++vp]=x;
     70     dvsp[x]=dvsp[ff]+1;fa[x][0]=ff;
     71     insert(root[ff],root[x],1,vt,val[x]);
     72     for (int i=st[x];i!=-1;i=vs[i].next)
     73         if (vs[i].v!=ff)
     74         Rebuild(vs[i].v,x);
     75 }
     76 void merge(int x,int y)
     77 {
     78     int fx=find(x),fy=find(y);
     79     if (size[fx]>size[fy]) swap(x,y),swap(fx,fy);
     80     vp=0; vsadd(x,y),vsadd(y,x);
     81     Rebuild(x,y);
     82     ffa[fx]=fy;
     83     size[fy]+=size[fx];
     84     for (int i=1;i<=20;i++)
     85         for (int j=1;j<=vp;j++)
     86             fa[sta[j]][i]=fa[fa[sta[j]][i-1]][i-1];
     87 }
     88 int Query(int x,int y,int z)
     89 {
     90     int Lca=lca(x,y);
     91     return query(root[x],root[y],root[Lca],root[fa[Lca][0]],1,vt,z);
     92 }
     93 int lastans;char s[5];
     94 int main()
     95 {
     96     memset(st,-1,sizeof(st));
     97     scanf("%d",&T);
     98     scanf("%d%d%d",&n,&m,&q);
     99     for (int i=1;i<=n;i++)scanf("%d",&val[i]),a[i]=val[i];
    100     sort(a+1,a+n+1);
    101     vt=unique(a+1,a+n+1)-a-1;
    102     for (int i=1;i<=n;i++) val[i]=lower_bound(a+1,a+vt+1,val[i])-a;
    103     for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),vsadd(x,y),vsadd(y,x);
    104     for (int i=1;i<=n;i++) ffa[i]=i,size[i]=1;
    105     for (int i=1;i<=n;i++) if(!root[i])dfs(i,0);
    106     for (int i=1;i<=20;i++)
    107         for (int j=1;j<=n;j++)
    108             fa[j][i]=fa[fa[j][i-1]][i-1];
    109     for (int i=1;i<=q;i++)
    110     {
    111         scanf("%s",s);
    112         if(s[0]=='Q')
    113         {
    114             scanf("%d%d%d",&x,&y,&z);
    115             x^=lastans,y^=lastans,z^=lastans;
    116             int ret=Query(x,y,z);
    117             printf("%d
    ",a[ret]);
    118             lastans=a[ret];
    119         }
    120         else scanf("%d%d",&x,&y),x^=lastans,y^=lastans,merge(x,y);
    121     }
    122 }
    View Code

    还是太NAIVE了

  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/wcz112/p/6255153.html
Copyright © 2011-2022 走看看