热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[LOJ3140][COI2019]TENIS

神奇滴很的结论题。若选手\(u\)能够在至少一个场地战胜选手\(v\),则连一条\((u,v)\)的有向边。选手\(u\)能够获胜即从点\(u\)出发能到达其他所有结点。我们把强连

神奇滴很的结论题。

若选手 \(u\) 能够在至少一个场地战胜选手 \(v\),则连一条 \((u, v)\) 的有向边。选手 \(u\) 能够获胜即从点 \(u\) 出发能到达其他所有结点。

我们把强连通分量缩成一个点,由于该图类似竞赛图,容易发现缩完点后构成了一条有向链,每一个结点都向它后面的所有结点连边。

显然,有且仅有链头的强连通分量内的点能够获胜。

考虑同一个强连通分量内的点对应到给出的三个数组上有什么性质。

手玩发现,强连通分量纵向地划分了这三个数组。

给三个数组间相同的数连边,可以发现划分的位置就是没有边经过的位置。

考虑证明该性质。

对于链上相邻两个强连通分量,靠前的强连通分量中的每个点一定在三个数组中都位于靠后的强连通分量中每个点的前面。即它们在链上一定会形成一个划分。

同时,不难证明每一个划分两侧的点都属于不同的强连通分量。

所以该性质得证。

所以我们只需找出三个数组中第一个没有被边经过的间隙即可回答询问。

由于带修,所以用线段树实现。

#include
using namespace std;
const int MAXN = 1e5 + 10;
int n, m, rk[MAXN][3], mn[MAXN * 4], tag[MAXN * 4];
inline int ls(int p) { return p <<1; }
inline int rs(int p) { return p <<1 | 1; }
inline void push_up(int p) { mn[p] = min(mn[ls(p)], mn[rs(p)]); }
inline void get_down(int p, int x) { mn[p] += x, tag[p] += x; }
inline void push_down(int p) {
if (!tag[p]) return;
get_down(ls(p), tag[p]);
get_down(rs(p), tag[p]);
tag[p] = 0;
}
void update(int p, int l, int r, int ql, int qr, int x) {
if (ql <= l && r <= qr) {
get_down(p, x);
return;
}
push_down(p);
int mid = (l + r) >> 1;
if (ql <= mid) update(ls(p), l, mid, ql, qr, x);
if (qr > mid) update(rs(p), mid + 1, r, ql, qr, x);
push_up(p);
}
int find(int p, int l, int r) {
if (l == r) return l;
push_down(p);
int mid = (l + r) >> 1;
if (mn[ls(p)]) return find(rs(p), mid + 1, r);
return find(ls(p), l, mid);
}
void add(int x, int y) {
int l = *min_element(rk[x], rk[x] + 3), r = *max_element(rk[x], rk[x] + 3);
if (l != r) update(1, 1, n, l, r - 1, y);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int j = 0, x; j <3; ++j)
for (int i = 1; i <= n; ++i) cin >> x, rk[x][j] = i;
for (int i = 1; i <= n; ++i) add(i, 1);
while (m--) {
int typ;
cin >> typ;
if (typ == 1) {
int x;
cin >> x;
cout <<(rk[x][0] <= find(1, 1, n) ? "DA" : "NE") <<"\n";
} else {
int p, u, v;
cin >> p >> u >> v, --p;
add(u, -1), add(v, -1);
swap(rk[u][p], rk[v][p]);
add(u, 1), add(v, 1);
}
}
return 0;
}


推荐阅读
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 探索1000以内的完美数:因数和等于自身
    本文探讨了如何在1000以内找到所有完美数,即一个数的因数(不包括自身)之和等于该数本身。例如,6是一个完美数,因为1 + 2 + 3 = 6。通过编程实现这一过程,可以更好地理解完美数的特性。 ... [详细]
author-avatar
三八依依2010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有