这题看到后我的第一想法是用set
开一个set存储当前还存活的人
每次给一个l和r后,在set里lower_bound一下,然后除了胜利者的人都erase掉
因为每个元素进set一次,出set一次,所以是O(nlogn)的
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <utility>
#include <map>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <deque>
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define LL long long
#define Pair pair<int,int>
#define LOWBIT(x) x & (-x)
using namespace std;
const int MOD=1e9+7;
const int INF=0x7ffffff;
const int magic=348;
int n,m;
set<int> s;
set<int>::iterator lit,rit,iter;
int ans[300048];
int dd[300048],top=0;
void init()
{
int i;
for (i=1;i<=n;i++) s.insert(i);
}
int main ()
{
int i,j,l,r,winner;
scanf("%d%d",&n,&m);
init();
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&winner);
lit=s.lower_bound(l);rit=s.lower_bound(r);
if (*rit==r) rit++;
top=0;
for (iter=lit;iter!=rit;iter++)
if (*iter!=winner)
{
ans[*iter]=winner;
dd[++top]=*iter;
}
for (j=1;j<=top;j++) s.erase(dd[j]);
}
for (i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}
后来想到一种更好的用dsu的算法
暴力的解法是O(n*n),瓶颈在于已经被删除的元素被重复考虑
所以我们可以用dsu来跳过那些已经被删除的元素
如果一个选手x已经被打败,那么就合并x和x+1
这样在循环的时候不断的找anc,每个元素仅被找到一次,O(n)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <utility>
#include <map>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#include <deque>
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define LL long long
#define Pair pair<int,int>
#define LOWBIT(x) x & (-x)
using namespace std;
const int MOD=1e9+7;
const int INF=0x7ffffff;
const int magic=348;
int ans[300048];
int pre[300048];
int find_anc(int x)
{
if (pre[x]!=x) pre[x]=find_anc(pre[x]);
return pre[x];
}
void update(int x,int y)
{
x=find_anc(x);y=find_anc(y);
pre[x]=y;
}
int n,m;
int main ()
{
int i,j,l,r,winner;
scanf("%d%d",&n,&m);
for (i=1;i<=n+1;i++) pre[i]=i;
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&l,&r,&winner);
for (j=find_anc(l);j<=r;j=find_anc(j))
{
if (j!=winner)
{
ans[j]=winner;
update(j,j+1);
}
else
j++;
}
for (i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}