构造 满足若干个区间(任意两个区间不交或包含)逆序对个数为奇/偶 的 序列

文章描述了一个使用C++编写的算法,解决给定区间内数字奇偶性的问题。通过定义结构体和使用深度优先搜索(dfs),调整区间内的数字顺序以满足特定奇偶性要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 5;
struct node
{
	int l, r, w;//[l, r]是下标区间,要求下标区间[l, r]上的数字在[l, r]范围
} a[maxn];
vector<int> G[maxn];
int pos[maxn]; // pos[i]表示数字i的位置
int deg[maxn], b[maxn];
bool cmp1(node a, node b)
{
	return a.r - a.l < b.r - b.l;
}
bool cmp2(int x, int y)
{
	return a[x].l < a[y].l;
}
void dfs(int u)
{
	int w = a[u].w;
	if (G[u].empty())
	{ // 叶子结点,区间长度至少为2,直接交换第一个和第二个
		if (w == 1)
			swap(pos[a[u].l], pos[a[u].l + 1]);
		return;
	}
	for (auto v : G[u])
	{
		dfs(v); // 先搞好所有子树的逆序对奇偶性
		w ^= a[v].w;
	}
	if (w == 0) // 说明搞好子树的逆序后,当前结点的奇偶性恰好为题目要求,直接return
		return;
	sort(G[u].begin(), G[u].end(), cmp2);
	int v = G[u][0], v1 = G[u][1];
// 	如果当前所有子区间逆序对奇偶性与大区间不同,考虑在第一个区间[l1, r1]和第一个不在第一个区间的位置
// 进行交换。分为以下几种情况:
// (a) l1 = l, 考虑交换数字r1和数字r1+1。如果r1 + 1 = l2(即两个区间拼接在一起),则找到下标[l2, r2]上的最小值(l2)与[l1, r1]上的最大值(r1)交换。如果
// r1 + 1 < l2(即两个区间不是拼接在一起),则直接交换下标[l1, r1]上的最大值和数字r1 + 1。这样交换不会影响子树的逆序对奇偶性,只会影响当前结点及其祖先结点
// (b) r1 = r考虑交换数字l1 - 1和数字l1。找到下标[l1, r1]上的最大值与数字l1 - 1交换。
	if (a[v].l == a[u].l)
	{//搞完子树逆序后,子结点对于的下标区间[l1, r1]上的数的范围是[l1, r1]
		swap(pos[a[v].r], pos[a[v].r + 1]);
	}
	else
		swap(pos[a[v].l], pos[a[v].l - 1]);
}
int main()
{
	int n, m, i, j;
	cin >> n >> m;
	for (i = 1; i <= n; i++)
		pos[i] = i;
	for (i = 1; i <= m; i++)
	{
		cin >> a[i].l >> a[i].r >> a[i].w;
		if (a[i].l == a[i].r && a[i].w)
		{
			cout << -1;
			return 0;
		}
	}
	sort(a + 1, a + m + 1, cmp1);
	for (i = 1; i <= m; i++)
	{
		for (j = i + 1; j <= m; j++)
		{//区间只有包含或者不交的关系,联系到树形结构
			if (a[j].l <= a[i].l && a[j].r >= a[i].r)
			{
				G[j].push_back(i);
				deg[i]++;
				break;
			}
		}
	}
	for (i = 1; i <= m; i++)
	{
		if (!deg[i])
			dfs(i);
	}
	for (i = 1; i <= n; i++)
		b[pos[i]] = i;
	for (i = 1; i <= n; i++)
		cout << b[i] << ' ';
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__night_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值