题目
#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;
}