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

    题意:

    强制在线

    1.查询树上两点间权值第k小

    2.连接两棵树

    题解:

    首先这题数据不得不吐槽

    数据数字大小都是超过1e7的???

    洛谷上又不能下载数据又只能显然re的 对拍了半天也没搞出来错(加上生成器还很难写)

    查找第k大显然可以用主席树

    而连接两棵树又是lct

    考虑一下怎么搞,lct显然是不能用splay来维护区间k大的 只能放弃了

    考虑用主席树维护每个点到根的路径

    建树很简单

    那么怎么合并呢

    是可以用启发式合并暴力重构的(总共nlogn次插入,插入复杂度logn,总时间nlog2n)

    那么考虑查询,平时在普通的主席树上查询是f(y)-f(x-1)

    那么在树上就变成了f(x)+f(y)-2f(lca(x,y))再加上一下lca(x,y)

    当然为了防止特判可以变成f(x)+f(y)-f(lca(x,y))-f(fa(lca(x,y))

    求lca只需要在合并时暴力维护倍增数组就可以了(nlog2n)

    所以总的时间复杂度是(nlog2n)

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 100000
    #define INF 1000000000
    struct re{
        int a,b;
    }a[maxn*2];
    struct ree{
        int h,t,x;
    }p[20000000];
    int bz[maxn][18],dep[maxn],root[maxn],v[maxn];
    int l,now,head[maxn],count2[maxn],faa[maxn],n,m,t;
    bool f[maxn];
    void arr(int x,int y)
    {
        a[++l].a=head[x];
        a[l].b=y;
        head[x]=l;
    }
    #define mid (h+t)/2
    void insert(int &x,int y,int v,int h,int t)
    {
        x=++now;
        p[x]=p[y]; p[x].x++;
        if (h==t) return; 
        if (mid>=v) insert(p[x].h,p[y].h,v,h,mid);
        else insert(p[x].t,p[y].t,v,mid+1,t);
    }
    void dfs(int x,int fa,int zx)
    {
        insert(root[x],root[fa],v[x],1,INF); dep[x]=dep[fa]+1;
        f[x]=0; bz[x][0]=fa; count2[x]=1;
        faa[x]=zx;
        int u=head[x];
        while (u)
        {
            int v=a[u].b;
            if (v!=fa)
            { 
              dfs(v,x,zx);
              count2[x]+=count2[v];
            }
            u=a[u].a;
        }
    }
    void dfs2(int x,int fa,int zx)
    {
           insert(root[x],root[fa],v[x],1,INF); faa[x]=zx; dep[x]=dep[fa]+1;
           bz[x][0]=fa;
           for (int i=1;i<=17;i++)
             bz[x][i]=bz[bz[x][i-1]][i-1];
           int u=head[x];
           while (u)
           {
            int v=a[u].b;
            if (v!=fa)
            {
                dfs2(v,x,zx);
            }
            u=a[u].a;
        }
    } 
    void merge(int x,int y)
    {
        if (count2[faa[x]]<count2[faa[y]]) swap(x,y);
        count2[faa[x]]+=count2[faa[y]];
        dfs2(y,x,faa[x]);
    }
    int get_lca(int x,int y)
    {
        if (dep[x]<dep[y]) swap(x,y);
        for (int i=17;i>=0;i--)
          if (dep[x]-(1<<i)>=dep[y]) x=bz[x][i];
        if (x==y) return(x);
        for (int i=17;i>=0;i--)
          if (bz[x][i]!=bz[y][i])
          {
              x=bz[x][i]; y=bz[y][i];
          }
        return(bz[x][0]);
    }
    int js(int x)
    {
        return(p[p[x].h].x);
    }
    int query(int c,int d,int x,int y,int k,int h,int t)
    {
        if (h==t) return(h);
        int tmp=js(x)+js(y)-js(c)-js(d);
        if (tmp<k) return (query(p[c].t,p[d].t,p[x].t,p[y].t,k-tmp,mid+1,t));
        else return (query(p[c].h,p[d].h,p[x].h,p[y].h,k,h,mid));
    }
    int main()
    {
        freopen("noip.in","r",stdin);
        freopen("noip.out","w",stdout);
        int tmp;
        cin>>tmp;
        cin>>n>>m>>t;
        int c,d,e;
        for (int i=1;i<=n;i++) cin>>v[i];
        for (int i=1;i<=m;i++)
        {
            cin>>c>>d; arr(c,d); arr(d,c);
        }
        memset(f,1,sizeof(f));
        for (int i=1;i<=n;i++) if (f[i]) dfs(i,0,i);
        for (int i=1;i<=17;i++)
          for (int j=1;j<=n;j++)
            bz[j][i]=bz[bz[j][i-1]][i-1];
        int ans=0;
        char cc;
        for (int i=1;i<=t;i++)
        {
            cin>>cc;
            if (cc=='Q')
            {
                cin>>c>>d>>e;
                c=c^ans; d=d^ans; e=e^ans;
                int x=get_lca(c,d),y=bz[x][0];
                ans=query(root[x],root[y],root[c],root[d],e,1,INF);
                cout<<ans<<endl;
            } else
            {
                cin>>c>>d;
                c=c^ans; d=d^ans;
                merge(c,d);
                arr(c,d); arr(d,c);
              }
    //          ans=0;
        }
        return 0;
    }
  • 相关阅读:
    Elasticsearch Network Settings
    Spring Application Event Example
    hibernate persist update 方法没有正常工作(不保存数据,不更新数据)
    快速自检电脑是否被黑客入侵过(Linux版)
    快速自检电脑是否被黑客入侵过(Windows版)
    WEB中的敏感文件泄漏
    Nginx日志分析
    关系型数据库设计小结
    软件开发的一些"心法"
    关于DNS,你应该知道这些
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8496772.html
Copyright © 2011-2022 走看看