首页 > 其他分享 >P3224 [HNOI2012] 永无乡

P3224 [HNOI2012] 永无乡

时间:2024-11-29 11:01:19浏览次数:7  
标签:return lc val leq int 永无 HNOI2012 编号 P3224

[HNOI2012] 永无乡

题目描述

永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 \(a\) 出发经过若干座(含 \(0\) 座)桥可以 到达岛 \(b\) ,则称岛 \(a\) 和岛 \(b\) 是连通的。

现在有两种操作:

B x y 表示在岛 \(x\) 与岛 \(y\) 之间修建一座新桥。

Q x k 表示询问当前与岛 \(x\) 连通的所有岛中第 \(k\) 重要的是哪座岛,即所有与岛 \(x\) 连通的岛中重要度排名第 \(k\) 小的岛是哪座,请你输出那个岛的编号。

输入格式

第一行是用空格隔开的两个整数,分别表示岛的个数 \(n\) 以及一开始存在的桥数 \(m\)。

第二行有 \(n\) 个整数,第 \(i\) 个整数表示编号为 \(i\) 的岛屿的排名 \(p_i\)。

接下来 \(m\) 行,每行两个整数 \(u, v\),表示一开始存在一座连接编号为 \(u\) 的岛屿和编号为 \(v\) 的岛屿的桥。

接下来一行有一个整数,表示操作个数 \(q\)。

接下来 \(q\) 行,每行描述一个操作。每行首先有一个字符 \(op\),表示操作类型,然后有两个整数 \(x, y\)。

  • 若 \(op\) 为 Q,则表示询问所有与岛 \(x\) 连通的岛中重要度排名第 \(y\) 小的岛是哪座,请你输出那个岛的编号。
  • 若 \(op\) 为 B,则表示在岛 \(x\) 与岛 \(y\) 之间修建一座新桥。

输出格式

对于每个询问操作都要依次输出一行一个整数,表示所询问岛屿的编号。如果该岛屿不存在,则输出 \(-1\) 。

样例 #1

样例输入 #1

5 1
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3

样例输出 #1

-1
2
5
1
2

提示

数据规模与约定

  • 对于 \(20\%\) 的数据,保证 \(n \leq 10^3\), \(q \leq 10^3\)。
  • 对于 \(100\%\) 的数据,保证 \(1 \leq m \leq n \leq 10^5\), \(1 \leq q \leq 3 \times 10^5\),\(p\) 为一个 \(1 \sim n\) 的排列,\(op \in \{\texttt Q, \texttt B\}\),\(1 \leq u, v, x, y \leq n\)。

分析

并查集维护连通性,线段树合并。 $ root[i] $ 数组记录根编号为 $ fa[i] $ 的联通块的权值线段树。

每次修改合并直接合并两个联通块的信息。

注意线段树合并不能自己合并自己,会导致叶节点权值错误影响答案。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;

int n,m,q;
int g[N],f[N];
int root[N<<5],tot,rk[N];
int fin(int x){return (f[x]==x)?(x):(f[x]=fin(f[x]));}
struct segtree{int lc,rc,val,id;}s[N<<5];
void upd(int &i,int l,int r,int x)
{
    if(!i)i=++tot;
    ++s[i].val;
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(x<=mid)upd(s[i].lc,l,mid,x);
    else upd(s[i].rc,mid+1,r,x);
}
void merg(int &i,int &j,int l,int r)//i<--j
{
    if(i==0 || j==0){i+=j;return ;}
    if(l==r)
    {
        s[i].val+=s[j].val;
        return ;
    }
    int mid=(l+r)>>1;
    merg(s[i].lc,s[j].lc,l,mid);
    merg(s[i].rc,s[j].rc,mid+1,r);
    s[i].val=s[s[i].lc].val+s[s[i].rc].val;
}
void init()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;++i)
    {
        scanf("%d",&x);
        upd(root[i],1,n,x);
        f[i]=i;
        rk[x]=i;
    }
    for(int i=1,x,y,fx,fy;i<=m;++i)
    {
        scanf("%d%d",&x,&y);
        fx=fin(x);
        fy=fin(y);
        if(fx!=fy)
        {
            merg(root[fx],root[fy],1,n);
            f[fy]=fx;
        }
    }
}
int que(int i,int l,int r,int k)
{
    if(i==0 && k>0)return -1;
    if(l==r)
        return (s[i].val==k)?(l):(-1);

    int mid=(l+r)>>1,sum=s[s[i].lc].val;
    if(sum>=k)return que(s[i].lc,l,mid,k);
    else return que(s[i].rc,mid+1,r,k-sum);
}
void work()
{
    scanf("%d",&q);
    while(q--)
    {
        char t=getchar();
        int x,y;
        while(t!='Q' && t!='B')t=getchar();
        scanf("%d%d",&x,&y);
        if(t=='Q')
        {
            int ans=que(root[fin(x)],1,n,y);
            if(ans==-1)printf("-1\n");
            else
            printf("%d\n",rk[ans]);
        }
        else
        {
            int fx=fin(x),fy=fin(y);
            if(fx==fy)continue;
            merg(root[fx],root[fy],1,n);
            f[fy]=fx;
        }
    }
}

int main()
{
    init();
    work();
    return 0;
}

标签:return,lc,val,leq,int,永无,HNOI2012,编号,P3224
From: https://www.cnblogs.com/Glowingfire/p/18576099

相关文章

  • P3224[HNOI2012]永无乡
    P3224[HNOI2012]永无乡(超详细!)居然没有人写平板电视库的题解(pbdsyyds)不了解pbds库的可以去看oiwiki或者上网学习。题目大意给定一个无向图,询问\(x\)所在连通块排名第\(y\)的点,且带加边修改。刚开始每个点属于一个连通块,\(m\)条边可以看做\(m\)个加边的操作。思......
  • [lnsyoj300/luoguP3224/HNOI2012]永无乡
    题意给定\(n\)个集合,每个集合最开始只包含数\(a_i\),然后进行\(m\)次合并操作。具体地,每次操作将数\(a_i\)所在的集合与数\(a_j\)所在的集合合并。接下来,进行\(q\)次操作,每次操作可能为合并操作与查询操作,合并操作与上述相同,查询操作为查询数\(a_x\)所在的集合中第......
  • [HNOI2012] 矿场搭建 题解
    [HNOI2012]矿场搭建前置知识:#Tarjan求点双连通分量题目大意​ 给你一张无向连通图,任意删去其中一个点,要求在删点后在每个连通块中有一个点被选择,问至少需要选择多少个点,以及选择的方案数。输入输出格式输入​ 多组数据以\(N=0\)结束​ 每组数据第一行为边的数量\(N\(N......
  • P3219 [HNOI2012] 三角形覆盖问题&P1222 三角形 题解
    严格单$\log$做法,附实现细节和代码。考虑从左往右扫描线,发现每次操作是线段上端点$-1$,插入线段,删除退化成点的线段。如果某时刻一条线段被另一条完全覆盖,那么这条线段显然不会产生贡献,可以删去。最后得到的线段一定是左端点单调递增时,右端点也单调递增,可以用set维护。当两......
  • 【题解】HNOI2012 - 集合选数
    HNOI2012-集合选数https://www.luogu.com.cn/problem/P3226不算难的非显然状压dp。首先根据限制条件建图,\((x,2x),(x,3x)\)连边,表示边上相邻两个点不能同时选,然后一组独立集就是一个可行的集合。发现画出来的图是若干个部分网格图,每个连通块最小的点都是与\(6\)互质的数......
  • 佛祖保佑 永无bug 永不宕机
    _ooOoo_o8888888o88"."88(|-_-|)O\=/O____/`---'\____.'\\||//`./\\|||:|||//\......
  • 大型网站技术架构:核心原理与案例分析—第六章:永无止境:网站的伸缩性架构
    1,网站架构的伸缩性设计一般说来,网站的伸缩性设计可分为两类,一类是根据功能进行物理分离实现伸缩;一类是单一功能通过集群实现伸缩。前者是不同的服务器部署不同的服务,提供不同的功能;后者是集群内的多台服务器部署相同的服务,提供相同的功能。1)不同功能进行物理分离实现伸缩每......
  • [HNOI2012] 集合选数
    [HNOI2012]集合选数目录题目描述输入格式输出格式样例#1样例输入#1样例输出#1提示题意概括思路历程:1.设计状态2.设计转移代码实现:题目描述《集合论与图论》这门课程有一道作业题,要求同学们求出\(\{1,2,3,4,5\}\)的所有满足以下条件的子集:若\(x\)在该子集中,则\(2......
  • BZOJ 2730: [HNOI2012]矿场搭建 tarjan割点
    2730:[HNOI2012]矿场搭建TimeLimit: 10Sec  MemoryLimit: 128MBSubmit: 2010  Solved: 935[Submit][Status][Discuss]Description煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口......
  • 佛祖保佑,永无bug
    fozu(){return["_ooOoo_","o8888888o","88\".\"88","(|-_-|)","O\\=/O",&......