UVA1455 – Kingdom(并查集 + 线段树)

UVA1455 – Kingdom(并查集 + 线段树)

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

UVA1455 – Kingdom(并查集 + 线段树)

题目链接

题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum (浮点数小数点一定是0.5) 查询y = fnum这条直线穿过了多少个州和city。州指的是连通的城市。

解题思路:用并查集记录城市之间是否连通,还有每一个州的y的上下界。建立坐标y的线段树,然后每次运行road操作的时候,对范围内的y坐标进行更新;更新须要分三种情况:两个州是相离,还是相交,还是包括(这里指的是y坐标的关系);而且由于这里查询是浮点数,所以更新的时候[l,r]的时候,仅仅更新[l,r),这里的r留给它以下的点,这样每次查询的时候就能够查询(int)fnum。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1e6 + 5;
const int N = 1e5 + 5;
#define lson(x) (x<<1)
#define rson(x) ((x<<1) | 1)

struct Node {

    int l, r, ns, nc;
    void set (int l, int r, int ns, int nc) {

        this->l = l;
        this->r = r;
        this->ns = ns;
        this->nc = nc;
    }
}node[4 * maxn];

void pushup (int u) {

    node[u].set (node[lson(u)].l, node[rson(u)].r, 0, 0);
}

void add_node (int u, int adds, int addc) {

    node[u].ns += adds;
    node[u].nc += addc;    
}

void pushdown (int u) {

    if (node[u].ns || node[u].nc) {
        add_node(lson(u), node[u].ns, node[u].nc);
        add_node(rson(u), node[u].ns, node[u].nc);    
    }
}

void build (int u, int l, int r) {

    if (l == r) {
        node[u].set (l, r, 0, 0);
        return;
    }

    int m = (l + r)>>1;
    build (lson(u), l, m);
    build (rson(u), m + 1, r);
    pushup(u);
}

void update (int u, int l, int r, int addc, int adds) {

    if (node[u].l >= l && node[u].r <= r) {
        add_node (u, adds, addc);    
        return;
    }

    int m = (node[u].l + node[u].r)>>1;
    pushdown(u);
    if (l <= m)
        update (lson(u), l, r, addc, adds);
    if (r > m)
        update (rson(u), l, r, addc, adds);
    pushup(u);
}

int query (int u, int x) {

    if (node[u].l == x && node[u].r == x)
        return u;

    int m = (node[u].l + node[u].r)>>1;
    int ans;

    pushdown(u);
    if (x <= m)
        ans = query (lson(u), x);
    else
        ans = query (rson(u), x);
    pushup(u);
    return ans;
}

int p[N], cnt[N], L[N], R[N];
int n, m;

int getParent (int x) {
    return x == p[x] ? x: p[x] = getParent (p[x]);
}

void change (int u, int l, int r, int addc, int adds) {

    if (r < l) //注意
        return;
    update (u, l, r, addc, adds); 
}

void Union(int x, int y) {

    x = getParent (x);
    y = getParent (y);

    if (x == y)
        return;

    if (L[x] >= L[y])
        swap(x, y);

    if (R[x] <= L[y]) {//相离

        change (1, L[x], R[x] - 1, cnt[y], 0);        
        change (1, L[y], R[y] - 1, cnt[x], 0);
        change (1, R[x], L[y] - 1, cnt[x] + cnt[y], 1);
    } else if (R[y] <= R[x]) {//包括

        change (1, L[x], L[y] - 1, cnt[y], 0);
        change (1, R[y], R[x] - 1, cnt[y], 0);
        change (1, L[y], R[y] - 1, 0, -1);
    } else {//相交

        change (1, L[x], L[y] - 1, cnt[y], 0);
        change (1, R[x], R[y] - 1, cnt[x], 0);
        change (1, L[y], R[x] - 1, 0, -1);
    }

    p[x] = y;
    cnt[y] += cnt[x];
    L[y] = min (L[y], L[x]);
    R[y] = max (R[y], R[x]);
}

void init () {

    int x, y;
    scanf ("%d", &n);

    for (int i = 0; i < n; i++) {
        scanf ("%d%d", &x, &y);
        p[i] = i;
        cnt[i] = 1;
        L[i] = R[i] = y;

    }

    scanf ("%d", &m);
    build (1, 0, maxn - 5);
}

void solve () {

    char str[100];
    int x, y;
    double q;

    for (int i = 0; i < m; i++) {

        scanf ("%s", str);

        if (str[0] == 'r') {
            scanf ("%d%d", &x, &y);        
            Union(x, y);
        } else {
            scanf ("%lf", &q);
            x = query (1, (int)q);
            printf ("%d %d\n", node[x].ns, node[x].nc);
        }
    }
}

int main () {

    int T;
    scanf ("%d", &T);

    while (T--) {

        init();
        solve();    
    }
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/118052.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CompoundButton 选中/未选中状态的按钮「建议收藏」

    CompoundButton 选中/未选中状态的按钮「建议收藏」正文  一、结构    publicabstractclassCompoundButtonextendsButtonimplementsCheckable     java.lang.Object      android.view.View        android.widget.TextView          android.widge

    2022年5月6日
    72
  • 京东签到在哪儿_python爬虫教程

    京东签到在哪儿_python爬虫教程京东签到在哪里?有哪些步骤呢?最近很多朋友都在咨询小编京东签到在哪里,其实这个问题很简单,但是为了能够使更多的亲们了解京东签到在哪里,小编专门整理了这篇文章,希望阅读过后的亲们可以明确京东签到这个问题的答案。京东签到是为了给京东会员提供购物赠京豆、生日礼包、自营免运费、专享礼包等权益。提高京东商城会员之间的互动,增加用户粘性。一、京东签到在哪里,可以签到的入口1、京东金融APP打开后,右上角那个日…

    2022年9月17日
    0
  • 香港手机号正则表达式「建议收藏」

    香港手机号正则表达式「建议收藏」刚遇到一个问题,不了解香港手机号的规则,现在记录下来,方便以后查看香港手机号码正则:^([6|9])\d{7}$澳门手机号码正则:^[0][9]\d{8}$大陆:^[1][3-8]\d{9}$正则表达式:^[1][3-8]\d{9}$|^([6|9])\d{7}$|^[6]([8|6])\d{5}$这是规则:大陆:开头13-8号码

    2022年5月4日
    330
  • 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api

    基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api

    2021年11月4日
    42
  • mbus水表方案_水表安装合同模板

    mbus水表方案_水表安装合同模板MBUS水表协议2400!!8E1???偶校验???NOCTS/RTS1.查询水表地址FEFEFE68AAAAAAAAAAAAAAAA0303810A004916起始A0……………A6CTR_0DI0DI1CSFEFEFE68AAAAAAAAAAAAAAAA0303810A004916T

    2022年10月10日
    0
  • layui的layer弹出层和form表单

    layui的layer弹出层和form表单文章目录弹出层layerform表单增删改查所有代码如果想用layui来完成增删改查,那么要会用弹出层和form表单这两个组件是必须的,所以今天就来介绍一些如何用layui完成基本的增删改查弹出层layer因为layui的特性,每次不管使用哪个组件,都要先把它的模块加载出来比如我要用layer和form那么就需要先这样定义,你的操作都是在这个里面进行,当然页可以一次性加载所有模块,详情…

    2022年7月13日
    18

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号