Distinct Values HDU 6301(贪心+线段树)
题目链接
题目大意:t组数据,n个点,m个限制条件,限制条件L, R是说L,R区间里面不能有重复的元素。然后让你构造出一个符合这些条件的一个序列。
样例:
3
2 1
1 2
4 2
1 2
3 4
5 2
1 3
2 4
输出:
1 2
1 2 1 2
1 2 3 1 1
#include <bits/stdc++.h>
using namespace std;
#define lson root << 1
#define rson root << 1 | 1
#define MID int mid = (l + r) / 2
const int maxn = 2e5 + 10;
struct node {
int l, r;
bool operator < (const node &a) const {
if(a.l == l) return r < a.r;
return l < a.l;
}
}p[maxn];
int tree[maxn << 2], ans[maxn];
//线段树里标记为1的表示这个点已经用过了 0表示没有用过
void Insert(int root, int l, int r, int pos, int v) {
if(pos < l || pos > r) return ;
if(l == r) {
tree[root] += v;
return ;
}
MID;
Insert(lson, l, mid, pos, v);
Insert(rson, mid + 1, r, pos, v);
tree[root] = tree[lson] + tree[rson];
}
int query(int root, int l, int r) {
if(l == r) return l;
MID;
int sum = tree[lson];
if(sum != mid - l + 1) return query(lson, l, mid); //看它的左区间有没有都用过
//没有的话就去找 都用过的话就去右区间找
else return query(rson, mid + 1, r);
}
int main()
{
int t;
scanf("%d", &t);
while(t--) {
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++)
scanf("%d %d", &p[i].l, &p[i].r);
sort(p, p + m);
for(int i = 0; i <= n; i++) ans[i] = 0;
for(int i = 0; i < 4 * n; i++) tree[i] = 0;
int pos1 = p[0].l, pos2 = p[0].l;
for(int i = 0; i < m; i++)
{
for(int j = pos1; j < p[i].l; j++)
{
if(ans[j] == 0) continue;
Insert(1, 1, n, ans[j], -1); //不用的数丢进线段树
}
for(int j = max(p[i].l, pos2); j <= p[i].r; j++)
{
ans[j] = query(1, 1, n);
Insert(1, 1, n, ans[j], 1);
}
pos1 = p[i].l;
pos2 = max(pos2, p[i].r+1);
}
for(int i = 1; i <= n; i++)
printf("%d%c", ans[i] ? ans[i] : 1, i == n ? '\n' : ' ');
}
}