zoukankan      html  css  js  c++  java
  • BZOJ 3123 森林

    题解网上都有。。。

    注意主席树的写法吧。。。我这样写可能空间小点吧。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxv 80050
    #define maxe 200050
    using namespace std;
    int testcase,n,m,q,lastans=0,father[maxv],size[maxv],dis[maxv],anc[maxv][20],g[maxv],nume=1,val[maxv],hash[maxv];;
    int root[maxv],ls[maxv*50],rs[maxv*50],sum[maxv*50],x,y,k;
    char type[4];
    int tot=0,cnt=0,lab,times=0,vis[maxv];
    struct edge
    {
        int v,nxt;
    }e[maxe];
    void addedge(int u,int v)
    {
        e[++nume].v=v;e[nume].nxt=g[u];
        g[u]=nume;
    }
    int getfather(int x)
    {
        if (father[x]!=x) father[x]=getfather(father[x]);
        return father[x];
    }
    void build(int pre,int &now,int left,int right,int pos)
    {
        if (!now) now=++tot;sum[now]=sum[pre]+1;
        if (left==right) return;
        int mid=(left+right)>>1;
        if (pos<=mid) {build(ls[pre],ls[now],left,mid,pos);rs[now]=rs[pre];}
        else {build(rs[pre],rs[now],mid+1,right,pos);ls[now]=ls[pre];}
    }
    void dfs1(int x)
    {
        father[x]=lab;vis[x]=1;size[lab]++;
        build(root[anc[x][0]],root[x],1,n,val[x]);
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v==anc[x][0]) continue;
            dis[v]=dis[x]+1;anc[v][0]=x;
            for (int e=1;e<=19;e++) anc[v][e]=anc[anc[v][e-1]][e-1];
            dfs1(v);
        }
    }
    void dfs2(int x)
    {
        build(root[anc[x][0]],root[x],1,n,val[x]);
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v==anc[x][0]) continue;
            dis[v]=dis[x]+1;anc[v][0]=x;
            for (int e=1;e<=19;e++) anc[v][e]=anc[anc[v][e-1]][e-1];
            dfs2(v);
        }
    }
    int lca(int x,int y)
    {
        if (dis[x]<dis[y]) swap(x,y);
        for (int e=19;e>=0;e--)
        {
            if (dis[anc[x][e]]>=dis[y] && anc[x][e])
                x=anc[x][e];
        }
        if (x==y) return x;
        for (int e=19;e>=0;e--)
        {
            if (anc[x][e]!=anc[y][e])
            {
                x=anc[x][e];
                y=anc[y][e];
            }
        }
        return anc[x][0];
    }
    int ask(int t1,int t2,int t3,int t4,int left,int right,int k)
    {
        if (left==right) return left;
        int r=sum[ls[t1]]+sum[ls[t2]]-sum[ls[t3]]-sum[ls[t4]];
        int r1=sum[ls[t1]],r2=sum[ls[t2]],r3=sum[ls[t3]],r4=sum[ls[t4]];
        int mid=(left+right)>>1;
        if (k<=r) return ask(ls[t1],ls[t2],ls[t3],ls[t4],left,mid,k);
        else return ask(rs[t1],rs[t2],rs[t3],rs[t4],mid+1,right,k-r);
    }
    void link(int x,int y)
    {
        int f1=getfather(x),f2=getfather(y);
        if (size[f1]>size[f2]) {swap(f1,f2);swap(x,y);}
        father[f1]=f2;size[f2]+=size[f1];
        dis[x]=dis[y]+1;anc[x][0]=y;for (int e=1;e<=19;e++) anc[x][e]=anc[anc[x][e-1]][e-1];
        dfs2(x);
    }
    int main()
    {
        scanf("%d",&testcase);
        scanf("%d%d%d",&n,&m,&q);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);hash[++cnt]=val[i];
            father[i]=i;
        }
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);addedge(y,x);
        }
        sort(hash+1,hash+cnt+1);cnt=unique(hash+1,hash+cnt+1)-hash-1;
        for (int i=1;i<=n;i++) val[i]=lower_bound(hash+1,hash+cnt+1,val[i])-hash;
        times++;
        for (int i=1;i<=n;i++)
        {
            if (vis[i]) continue;
            lab=i;dfs1(i);
        }
        for (int i=1;i<=q;i++)
        {
            scanf("%s",&type);
            if (type[0]=='Q')
            {
                scanf("%d%d%d",&x,&y,&k);
                x^=lastans;y^=lastans;k^=lastans;
                int t=lca(x,y);
                lastans=hash[ask(root[x],root[y],root[t],root[anc[t][0]],1,n,k)];
                printf("%d
    ",lastans);    
            }
            else
            {
                scanf("%d%d",&x,&y);
                x^=lastans;y^=lastans;
                link(x,y);addedge(x,y);addedge(y,x);
            }
        }
        return 0;
    }
  • 相关阅读:
    ASPNET5应用程序启动
    DNX概述
    MySQL数据库管理员密码忘记如何修改?
    Rsync数据复制软件应用
    Centos7系统中Mysql数据库的安装
    基于Haproxy+Keepalived实现Haproxy的高可用
    源码编译安装Mariadb数据库的时候报错,/usr/bin/c++ doesn't support -std=c++11 or -std=c++0x, you need one that does.
    mariadb数据库的安装
    更改Ubuntu和Centos系统中的镜像源
    快速搭建ELK日志分析系统
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6422904.html
Copyright © 2011-2022 走看看