首页 > 其他分享 >ARC165F Make Adjacent

ARC165F Make Adjacent

时间:2023-09-18 18:23:56浏览次数:49  
标签:ch int Make 建图 add Adjacent void ARC165F

D1a5y。

记录 \(x(1\le x\le n)\) 出现位置分别为 \(l_x,r_x(l_x< r_x)\),讨论一下发现当两个数 \(x,y\) 满足 \(l_x<l_y,r_x<r_y\) 时操作后 \(x\) 一定出现在 \(y\) 前面,不然可以交换位置以达到更优步数。否则发现无论怎么操作发现都不影响答案。

所以我们将 \(x\) 描述为平面上的点 \((l_x,r_x)\),操作为依次在平面上选择一个点删去,且需要满足删去的点左下角没有还没被删的点。直接建图,将 \((l_x,r_x)\) 向所有 \((l_y,r_y),l_x<l_y,r_x<r_y\) 连边,跑字典序最小拓扑序就是最优解。

但是这样边数是 \(O(n^2)\) 的,注意到点数 \(O(n)\),考虑优化建图。

按照 \(l_x\) 从大到小扫描线,每次相当于对于一个 \(r_i\) 排序后的后缀连边。这样的连边是一段区间,可以线段树优化建图,线段树建立在 \(r\) 序列上。

但是 \(l_x\) 向左移动时会插入新的 \(r_x\),为了让上一时刻的连边不包含新插入的 \(r_x\),需要可持久化。

复杂度 \(O(n\log n)\)。

// Problem: F - Make Adjacent
// Contest: AtCoder - AtCoder Regular Contest 165
// URL: https://atcoder.jp/contests/arc165/tasks/arc165_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

namespace vbzIO {
    char ibuf[(1 << 20) + 1], *iS, *iT;
    #if ONLINE_JUDGE
    #define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
    #else
    #define gh() getchar()
    #endif
    #define mt make_tuple
    #define mp make_pair
    #define fi first
    #define se second
    #define pc putchar
    #define pb emplace_back
    #define ins insert
    #define era erase
    typedef tuple<int, int, int> tu3;
    typedef pair<int, int> pi;
    inline int rd() {
        char ch = gh();
        int x = 0;
        bool t = 0;
        while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
        while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
        return t ? ~(x - 1) : x;
    }
    inline void wr(int x) {
        if (x < 0) x = ~(x - 1), putchar('-');
        if (x > 9) wr(x / 10);
        putchar(x % 10 + '0');
    }
}
using namespace vbzIO;

const int N = 4e5 + 400;

pi p[N];
int n, tot, rt, a[N], in[N << 5], rp[N];
vector<int> g[N << 5], ans;

struct seg { int lc, rc; } tr[N << 5];

#define ls tr[x].lc
#define rs tr[x].rc
#define mid ((l + r) >> 1)

void add_edge(int u, int v) { if (u && v) g[u].pb(v), in[v]++; }
void add(int l, int r, int p, int q, int y, int &x) {
	tr[x = ++tot] = tr[y];
	if (l == r) return add_edge(x, q);
	if (p <= mid) add(l, mid, p, q, tr[y].lc, ls);
	else add(mid + 1, r, p, q, tr[y].rc, rs);
	add_edge(x, ls), add_edge(x, rs);
}

void upd(int l, int r, int s, int t, int p, int x) {
	if (!x) return;
	if (s <= l && r <= t) return add_edge(p, x);
	if (s <= mid) upd(l, mid, s, t, p, ls);
	if (t > mid) upd(mid + 1, r, s, t, p, rs);
}

priority_queue<pi, vector<pi>, greater<pi> > q;

void topo() {
	for (int i = 1; i <= tot; i++)
		if (!in[i]) q.push(mp((i <= n ? i : 0), i));
	while (!q.empty()) {
		pi p = q.top(); q.pop();
		int u = p.se;
		if (u <= n) ans.pb(u);
		for (int v : g[u]) {
			in[v]--;
			if (!in[v]) q.push(mp((v <= n ? v : 0), v));
		}
	}
}

int main() {
	n = tot = rd();
	for (int i = 1; i <= (n << 1); i++) {
		a[i] = rd();
		if (!p[a[i]].fi) p[a[i]].fi = i;
		else p[a[i]].se = i;
	}
	for (int i = 1; i <= n; i++) rp[p[i].fi] = p[i].se;
	for (int i = (n << 1); i; i--) {
		if (!rp[i]) continue;
		upd(1, (n << 1), rp[i], (n << 1), a[i], rt);
		add(1, (n << 1), rp[i], a[i], rt, rt);
	}
	topo();
	for (int i : ans) 
		wr(i), pc(' '), wr(i), pc(' ');
	return 0;
}

标签:ch,int,Make,建图,add,Adjacent,void,ARC165F
From: https://www.cnblogs.com/Ender32k/p/17712749.html

相关文章

  • CMake/001-Hello CMake
    开始学习使用CMake建立工程(本文以实践为目的,注重实践)1.先安装CMake 2.创建一个最简单的CMake工程a.准备工作(找一个空目录,建立如下文件)           b.hello.cpp文件内容如下#include<stdlib.h>#include<string.h>v......
  • Go 项目的 MAKE 工具
    Go项目的MAKE工具MAKE工具是Linux和Unix系统中一种常见的自动化构建工具,通常用于管理和组织软件项目。在Go语言中,使用MAKE工具可以轻松地管理和构建项目,并自动执行诸如编译、测试、安装等复杂的操作。下面将介绍如何在Go项目中使用MAKE工具,并说明其主要优势......
  • Ubuntu16.04下C语言编译及makefile应用
    一、不同环境下C语言的编译在Ubuntu16.04下:step1:编写main1.c主程序用nano编好,下面为主程序展示注意:1、主程序中函数的声明step2:编写子程序 step3:用gcc命令编译采用多个文件一起编译,输出放在main1中 gcc的常见用法:-c只生成目标文件不进行连接,用于对目标文件的分别......
  • 构建工具Premake
    构建工具Premake经常用VisualStudio写一些小程序来验证OpenCASCADE的功能,每次创建项目后都配置头文件,库路径,程序运行时还要配置Debug的环境变量,比较麻烦。也尝试过CMake和QMake,都不太理想。CMake学习曲线陡峭一点,还会生成一堆文件。QMake简单些,但是有的选项不支持。直到看到一个......
  • Codeforces Round 764 (Div. 3) B. Make AP
    有三个正整数\(a,b,c\)。需要执行以下操作严格一次:选择任意一个正整数\(m\)并让严格一个\(a,b,c\)之一乘以\(m\)。但不能改变他们的顺序。回答是否可以经过一次操作后使\(a,b,c\)变为等差。分类讨论题:三种情况满足一种即可。(已知\(a,b,c\geq1\))\(ma......
  • 简单介绍cmakelist的使用
    Windows平台1在文件夹中创建一个CPP文件;自己随便写一个主函数就行 写一个简单的c++main函数;2创建一个CMakeLists.txt文件,写上下列内容;可以使用notepad,会对一些字段自动补齐cmake_minimum_required(VERSION3.5FATAL_ERROR)Project(HELLOW-01LANGUAGESCXX)add_e......
  • makefile学习
    makefile目标:依赖文件tab命令如果依赖文件比目标文件新,则执行命令来重新生成目标文件。四个版本makefile对比version1:test:main.csub.csub.h gcc-otestmain.csub.cversion2:优点:当只有一个文件更新时,不用重复编译test:main.osub.o gcc-otestmain.osu......
  • Compile、Make和Build的区别
    Compile、Make和Build的区别 针对Java的开发工具,一般都有Compile、Make和Build三个菜单项,完成的功能的都差不多,但是又有区别。 编译,是将源代码转换为可执行代码的过程。编译需要指定源文件和编译输出的文件路径(输出目录)。Java的编译会将java编译为class文件,将非java的文件(一般成......
  • ros2迁移c++之package.xml、CMakeLists.txt及编译
    1、package.xml<package><!--1.根标签--> <name><!--2.包名--> <version><!--3.版本号--> <description><!--4.包描述--> <maintainer><!--5.维护者--> <......
  • CMAKE相对路径编译和python的ctypes引用
    CMAKE相对路径编译和python的ctypes引用cmake编译库使用相对路径cmake编译使用相对路径生成动态库,进而满足其他代码的调用,如python的ctypes由于ctypes能调用c,而不能调用c++,所以,使用externc来处理,使ctypes能够调用。externc在需要编译动态库cpp代码中,使用C的方式处理函数......