Codeforces 357C Knight Tournament【并查集】
来源:互联网 发布:数据库工作是干什么的 编辑:程序博客网 时间:2024/05/17 22:16
Hooray! Berl II, the king of Berland is making a knight tournament. The king has already sent the message to all knights in the kingdom and they in turn agreed to participate in this grand event.
As for you, you're just a simple peasant. There's no surprise that you slept in this morning and were late for the tournament (it was a weekend, after all). Now you are really curious about the results of the tournament. This time the tournament in Berland went as follows:
- There are n knights participating in the tournament. Each knight was assigned his unique number — an integer from 1 ton.
- The tournament consisted of m fights, in thei-th fight the knights that were still in the game with numbers at leastli and at mostri have fought for the right to continue taking part in the tournament.
- After the i-th fight among all participants of the fight only one knight won — the knight numberxi, he continued participating in the tournament. Other knights left the tournament.
- The winner of the last (the m-th) fight (the knight numberxm) became the winner of the tournament.
You fished out all the information about the fights from your friends. Now for each knight you want to know the name of the knight he was conquered by. We think that the knight numberb was conquered by the knight number a, if there was a fight with both of these knights present and the winner was the knight numbera.
Write the code that calculates for each knight, the name of the knight that beat him.
The first line contains two integers n,m (2 ≤ n ≤ 3·105; 1 ≤ m ≤ 3·105) — the number of knights and the number of fights. Each of the followingm lines contains three integers li, ri, xi(1 ≤ li < ri ≤ n; li ≤ xi ≤ ri) — the description of the i-th fight.
It is guaranteed that the input is correct and matches the problem statement. It is guaranteed that at least two knights took part in each battle.
Print n integers. If the i-th knight lost, then the i-th number should equal the number of the knight that beat the knight numberi. If the i-th knight is the winner, then thei-th number must equal 0.
4 31 2 11 3 31 4 4
3 1 4 0
8 43 5 43 7 62 8 81 8 1
0 8 4 6 4 8 6 1
Consider the first test case. Knights 1 and 2 fought the first fight and knight 1 won. Knights 1 and 3 fought the second fight and knight 3 won. The last fight was between knights 3 and 4, knight 4 won.
题目大意:
一共有N个人,M场已知的战斗,其中M场战斗给出三个元素l,r,x,对应表示编号从l到r的所有人都输给了x(本身输给自己不作数).
如果某人通过之前的战斗已经确定这个人能够输给谁了,那么其之后的战斗就不用参加了。
输出N个数,每个数表示对应当前这个人输给了谁,如果这个人是冠军,输出0.
思路:
1、问题转化:
就是给你M次操作,每次操作对应将【l,r】区间内抛去x这个位子不进行更新之外,如果没有被数值覆盖的部分,都要被x这个数进行覆盖,求最终解的情况。
2、人人都会暴力,直接对应将每个区间都按照上述要求模拟即可,但是显然会超时。
那么我们考虑进行优化。
我这里选择并查集进行优化。
设定:find(l)==find(r)表示从l到r范围内的数值都已经更新过了。
那么我们在合并的时候,显然要将编号大的作为祖先。
那么对应在更新的过程中,我们就可以知道对应在位子i的最右边被更新过的位子,其就是位子i的祖先,那么下一个需要更新的位子,显然就是find(i)+1。
那么我们在每一次更新的时候,直接将代码写成这样既可:
for(int i=l;i<=r;i=find(i)+1){ if(i==x)continue; if(ans[i]==0) { ans[i]=x; } if(i!=x&&i!=l) merge(i,i-1);//对应更新过了位子i的数值,那么就要和之前的部分相连接}
3、时间复杂度就降下来啦~
Ac代码:
#include<stdio.h>#include<string.h>using namespace std;int f[500060];int ans[500060];int find(int a){ int r=a; while(f[r]!=r) r=f[r]; int i=a; int j; while(i!=r) { j=f[i]; f[i]=r; i=j; } return r;}void merge(int a,int b){ int A,B; A=find(a); B=find(b); if(A!=B) { if(A>B) f[B]=A; else f[A]=B; }}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { memset(ans,0,sizeof(ans)); for(int i=1;i<=n;i++)f[i]=i; while(m--) { int l,r,x; scanf("%d%d%d",&l,&r,&x); if(find(l)==find(r))continue; else { for(int i=l;i<=r;i=find(i)+1) { if(i==x)continue; if(ans[i]==0) { ans[i]=x; } if(i!=x&&i!=l) merge(i,i-1); } } } for(int i=1;i<=n;i++) { printf("%d ",ans[i]); } printf("\n"); }}
- Codeforces 357C Knight Tournament【并查集】
- CodeForces - 357C C - Knight Tournament 并查集or set模拟
- codeforces 357C Knight Tournament
- A. Knight Tournament----并查集
- CodeForces 357C - Knight Tournament(模拟)
- Codeforces Round #207 (Div. 2) C. Knight Tournament (并查集缩点)
- CF 356A Knight Tournament(并查集)
- codeforces356A Knight Tournament 并查集或线段树成端更新
- Codeforces #356C: Knight Tournament 题解
- Knight Tournament CodeForces
- Codeforces Round #207 (Div. 2) C. Knight Tournament
- Codeforces Round #207 (Div. 2) C. Knight Tournament
- Codeforces Round #207 (Div. 2) C. Knight Tournament
- Codeforces Round #207 (Div. 2)---C. Knight Tournament(set乱搞)
- Codeforces Round #207 (Div. 2) C - Knight Tournament
- CodeForces 356A Knight Tournament 【线段树】
- [Codeforces 878C] Tournament
- Codeforces Round #207 (Div. 2)C. Knight Tournament(SET也可以搞定)
- 关于spring多数据配置-个人向
- Spark:聚类算法
- JSP基础--基础知识、四大域及九大隐式对象
- PCL中RANSAC使用,点云平面检测,显示,存储
- PHP正则匹配中文字符串
- Codeforces 357C Knight Tournament【并查集】
- UVa 11948 四叉树
- PHP删除数组中特定元素的两种方法
- 2016C语言期中测验——德勒函数
- win764位加载驱动方法整理
- 第十三周 Oj 学生成绩的处理
- HDU2047_阿牛的EOF牛肉串
- 用初次训练的SVM+HOG分类器在负样本原图上检测HardExample
- Oracle用户解锁