Codeforces 357C Knight Tournament【并查集】

来源:互联网 发布:数据库工作是干什么的 编辑:程序博客网 时间:2024/05/17 22:16

A. Knight Tournament
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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 ≤ nli ≤ 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.

Output

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.

Examples
Input
4 31 2 11 3 31 4 4
Output
3 1 4 0 
Input
8 43 5 43 7 62 8 81 8 1
Output
0 8 4 6 4 8 6 1 
Note

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");    }}







0 0
原创粉丝点击