POJ 3109 Inner Vertices 离散化+树状数组

news2024/11/24 10:48:20

一、题目大意

围棋棋盘,如果某个坐标上下左右的四个方向都存在棋子,那么ans+1,根据输入的棋子数量,求出ans的数量。

二、解题思路

题目中有说到如果程序不会结束,那么输出-1,这其实是无源之水,根本不会发生。

我们可以一列一列的循环,然后针对列建立一个树状数组(线段树也行,树状数组更快)

坐标比较大,需要离散化(离散化就是把有效坐标排好序去重放在数组里,然后用原坐标对应数字再数组元素的顺序来替换掉原坐标的算法,可以参阅《挑战程序设计》第三章-常用技巧精选,或者可以参考鄙人AOJ0531的拙作题解)本题目每个输入的棋子x和y是有效坐标,其余坐标均无效,因为没有棋子的行或列一定无法让ans+1。

之后根据列来排序,列一样的,就根据行来排序(pair默认的就行,first列,second行)

然后记录下每一行的最后一个棋子的坐标(可以定一个数组,初值设置1或0,循环一次所有的棋子,更新到每一行的最大列即可)

然后,同时记录一个bool型的标记数组,来代表某一行是否前面已经有个棋子,如下图

循环每一列的时候,把当前元素和当前列上一个元素之间的元素集体+1(树状数组操作)update(上一个元素的列+1,当前元素列-1,1)这里需要判断下上一个的列+1和当前列-1的大小,如果大于等于那就不要更新了

同时遇到每一行第一个棋子时,要把这一行标记上,然后这一行的位置更新到0(更新到0是因为这一行之前左边没有棋子,如果左边没有棋子,那么这些+1的情况,即便上下有子也不应该记录到答案里,为的就是防止下图中红色箭头的位置被错误记录了),这样下次再碰到这一行的棋子,就可以代表两者之间的部分位置可以加到答案里。

然后更新到每一行最后一列的时候(这里可以通过之前记录的行最大列的数组来判断是不是最后一列),如果这一行之前没有被标记过,即这一行的最后一个棋子左边没有棋子,那么这一行+1的那些坐标不算数,上下有子,右边也有,但是左边没有那就不行,直接continue。

如果这一行标记过,那那表左边有棋子,同时循环到的这一行的最后一个棋子是它右边的,然后更新树状数组时的区间边界是它上下的,那么树状数组求出这一行的数量,要加到ans里,我这个思路就是如下图所示,每一列右边的一些数子,就是遇到走过某一列的时候树状数组渲染到正常的样子(非树形求和的那种),然后红色的箭头的就代表走到某一行最后一列了增加ans,

表达的不清晰,见谅!

三、代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
P num[100010];
ll bit0[131080], bit1[131080], ans;
int x[100010], y[100010], xLen, yLen, n, n_, maxCol[100010];
bool activeRow[100010];
void input()
{
    for (int i = 1; i <= n_; i++)
    {
        scanf("%d%d", &num[i].first, &num[i].second);
        x[i] = num[i].first;
        y[i] = num[i].second;
        activeRow[i] = false;
        maxCol[i] = 1;
    }
    sort(x + 1, x + (1 + n_));
    sort(y + 1, y + (1 + n_));
}
void compress()
{
    xLen = 1;
    yLen = 1;
    for (int i = 2; i <= n_; i++)
    {
        if (x[xLen] != x[i])
        {
            x[++xLen] = x[i];
        }
        if (y[yLen] != y[i])
        {
            y[++yLen] = y[i];
        }
    }
    for (int i = 1; i <= n_; i++)
    {
        num[i].first = lower_bound(x + 1, x + (xLen + 1), num[i].first) - x;
        num[i].second = lower_bound(y + 1, y + (yLen + 1), num[i].second) - y;
        if (maxCol[num[i].second] < num[i].first)
        {
            maxCol[num[i].second] = num[i].first;
        }
    }
}
void init()
{
    n = 131072;
    for (int i = 0; i <= n; i++)
    {
        bit0[i] = 0LL;
        bit1[i] = 0LL;
    }
}
void updateBit0(int r, ll v)
{
    if (r <= 0)
    {
        return;
    }
    for (int i = r; i <= n; i = i + (i & (-i)))
    {
        bit0[i] = bit0[i] + v;
    }
}
void updateBit1(int r, ll v)
{
    if (r <= 0)
    {
        return;
    }
    for (int i = r; i <= n; i = i + (i & (-i)))
    {
        bit1[i] = bit1[i] + v;
    }
}
ll queryBit0(int r)
{
    ll sum = 0LL;
    for (int i = r; i > 0; i = i - (i & (-i)))
    {
        sum = sum + bit0[i];
    }
    return sum;
}
ll queryBit1(int r)
{
    ll sum = 0LL;
    for (int i = r; i > 0; i = i - (i & (-i)))
    {
        sum = sum + bit1[i];
    }
    return sum;
}
void update(int l, int r, ll v)
{
    updateBit0(l, (-1LL) * v * ((ll)(l - 1)));
    updateBit0(r + 1, v * ((ll)r));
    updateBit1(l, v);
    updateBit1(r + 1, (-1LL) * v);
}
ll query(int l, int r)
{
    ll allAmt = queryBit0(r);
    ll allAdd = queryBit1(r) * ((ll)r);
    ll leftAmt = queryBit0(l - 1);
    ll leftAdd = queryBit1(l - 1) * ((ll)(l - 1));
    return (allAmt + allAdd - leftAmt - leftAdd);
}
void solve()
{
    sort(num + 1, num + (1 + n_));
    ans = 0LL;
    for (int i = 1; i <= n_; i++)
    {
        if (i > 1 && num[i - 1].first == num[i].first && (num[i - 1].second + 1) < num[i].second)
        {
            update(num[i - 1].second + 1, num[i].second - 1, 1LL);
        }
        if (maxCol[num[i].second] == num[i].first && !activeRow[num[i].second])
        {
            continue;
        }
        if (maxCol[num[i].second] == num[i].first && activeRow[num[i].second])
        {
            ans = ans + query(num[i].second, num[i].second);
        }
        if (!activeRow[num[i].second])
        {
            ll oldVal = query(num[i].second, num[i].second);
            update(num[i].second, num[i].second, (-1LL) * oldVal);
            activeRow[num[i].second] = true;
        }
    }
}
int main()
{
    while (~scanf("%d", &n_))
    {
        input();
        compress();
        init();
        solve();
        ans = ans + ((ll)n_);
        printf("%lld\n", ans);
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1057227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Java操作Redis

要在Java程序中操作Redis可以使用Jedis开源工具。 一、jedis的下载 如果使用Maven项目&#xff0c;可以把以下内容添加到pom中 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId>…

【Python】函数(function)和方法(method)的区别

这里先说结论&#xff0c;为了满足心急的小伙伴&#xff1a;method与function的最大区别就是参数有无进行绑定。 自定义类Test&#xff1a; 首先先来一个自定义类&#xff1a; class Test:def Func_normal(arg):print(Func_normal:,arg)staticmethoddef Func_static(arg):pri…

在vite中使用react-router-dom-v6 路由报错 Uncaught SyntaxError: Unexpected token ‘<‘

解决方法&#xff1a;将路由表“routes”下面的"index.js"改成“index.jsx”&#xff0c;正确的文件如下图所示。

Springboo整合Sentinel

Springboo整合Sentinel 1.启动Sentinel java -jar sentinel-dashboard-1.8.6.jar2.访问localhost:8080到Sentinel管理界面(默认账号和密码都是sentinel) 3.引入依赖(注意版本对应) <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spr…

window环境下Redis7服务器的安装和运行

一、readis7的下载 由于在官网上没有window版本的redis下载&#xff0c;需要到github中去搜索&#xff0c;以下以redis7为例介绍redis的下载 下载地址&#xff1a;https://github.com/zkteco-home/redis-windows 也可以到百度网盘下载 链接&#xff1a;https://pan.baidu.com…

【JavaSE重点知识归纳】第3节:运算符(算术、关系、逻辑、位、移位、优先级)

目录 一&#xff1a;什么是运算符 二&#xff1a;算术运算符 1.基本四则运算符&#xff1a;加减乘除模&#xff08;、-、*、/、%&#xff09; 2.增量运算符&#xff08;、-、*、%&#xff09; 3.自增/自减运算符&#xff08;、--&#xff09; 三&#xff1a;关系运算符 四…

【Kafka专题】Kafka集群架构设计原理详解

目录 前言前置知识课程内容一、Kafka的Zookeeper元数据梳理1.1 zookeeper整体数据1.2 Controller Broker选举机制1.3 Leader Partition选举机制1.4 Leader Partition自动平衡机制*1.5 Partition故障恢复机制1.6 HW一致性保障-Epoch更新机制1.7 总结 学习总结感谢 前言 Kafka的…

R语言实现竞争风险模型(1)

#竞争风险模型 tmp <- data.frame(gene tiaoxuan[,5:6],OS.Time Train[,"Survival_months"], OS Train[,"CSS"],stringsAsFactors F) colnames(tmp) #方法1&#xff1a;riskregression library(riskRegression) fgr1<-FGR(Hist(OS.Time,OS)~gen…

K 个一组翻转链表(链表反转,固定长度反转)(困难)

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你链表的头节点head&#xff0c;每k个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是k的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。…

Android SELinux 参数语法介绍及基础分析

Android SELinux安全策略主要使用对象安全上下文的基础进行描述&#xff0c;通过主体和客体的安全上下文去定义主体是否有权限访问客体&#xff0c;称为TypeEnforcement 安全上下文&#xff08;Security Context&#xff09; SEAndroid中的安全上下文:共有4个部分组成分别为use…

STM32 定时器介绍--通用、高级定时器

目录 高级定时器 1.功能框图 1-时钟源 2-时基单元 3-输入捕获 4-输出比较 2.输入捕获的应用 3.输出比较的应用 4.初始化结构体 1-时基初始化结构体 2-输出比较结构体 3-PWM信号 周期和占空比的计算--以通用定时器为例 4-输入捕获结构体 5-断路和死区初始化结构体…

05. 机器学习入门 - 动态规划

文章目录 从一个案例开始动态规划 Hi, 你好。我是茶桁。 咱们之前的课程就给大家讲了什么是人工智能&#xff0c;也说了每个人的定义都不太一样。关于人工智能的不同观点和方法&#xff0c;其实是一个很复杂的领域&#xff0c;我们无法用一个或者两个概念确定什么是人工智能&a…

对一条Linux命令的解读(sed find egrep)

目录 1 sed -i的意义 2 $的作用 3 find . -type f的意义 4 -exec .... {} \;的意义 5 egrep -l的意义 6 综合以上 在前面的博客源码编译elfutils_金色熊族的博客-CSDN博客中&#xff0c;我使用了一条指令 sed -i s/-Werror//g $(find . -type f -exec egrep -l _no_Werr…

学信息系统项目管理师第4版系列15_资源管理基础

1. 项目资源 1.1. 实物资源 1.1.1. 着眼于以有效和高效的方式&#xff0c;分配和使用完成项目所需的实物资源 1.1.2. 包括设备、材料、设施和基础设施 1.2. 团队资源 1.2.1. 人力资源 1.2.2. 包含了技能和能力要求 2. 人力资源管理 2.1. 不仅是组织中最重要的资源之一&…

C语言结构体指针学习

结构体变量存放内存中&#xff0c;也有起始地址&#xff0c;定义一个变量来存放这个地址&#xff0c;那这个变量就是结构体指针&#xff1b; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…

【算法分析与设计】回溯法(上)

目录 一、学习要点1.1 回溯法1.2 问题的解空间1.3 0-1背包问题的解空间1.4 旅行售货员问题的解空间1.5 生成问题状态的基本方法 二、回溯法的基本思想三、回溯算法的适用条件四、递归回溯五、迭代回溯六、子集树与排列树七、装载问题八、批处理作业调度问题 一、学习要点 理解回…

Scala第十一章节

Scala第十一章节 1.模式匹配 2. Option 类型 3.偏函数 4.正则表达式 5.异常处理 6.提取器 7.案例&#xff1a;随机职业 scala总目录 文档资料下载

大数据Flink(九十五):DML:Window TopN

文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景

【C语言】模拟实现strstr

strstr这个库函数看到这个名字大概率猜不到这是什么函数&#xff0c; 但经过学习就可以很好的认识到这个函数 目录 介绍&#xff1a;模拟实现&#xff1a;思路&#xff1a;代码实现&#xff1a; 介绍&#xff1a; 可以看到此函数是用来寻找一个字符串中是否含有另一个字符串 代…

云安全之HTTP协议介绍补充

HTTP是一个基于TCP/IP通信协议来传递数据的协议&#xff0c;传输的数据类型为HTML文件、图片文件、查询结果等。HTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。 URI、URL、URN HTTP使用统一资源标识符(Uniform Resource ldentif…