Codeforces #356C: Knight Tournament 题解

来源:互联网 发布:试述数据库设计的步骤 编辑:程序博客网 时间:2024/05/15 12:49

这题看到后我的第一想法是用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);}elsej++;}for (i=1;i<=n;i++) printf("%d ",ans[i]);return 0;}


原创粉丝点击