【并查集思想的应用.】疯狂的涂色

  疯狂的涂色

 

小t非常喜爱画画,但是他还是一个初学者。他最近费尽千辛万苦才拜到小Q为师。小Q是画鸡蛋长大的,让小t一入门就拿着一张白纸条疯狂地涂色。假设纸条被划分成了n个区域,用1~n的整数从左到右顺序编号,小Q总共下达了m条指令。第i条指令是让小t把编号为(i*p+q)mod n+1与(i*q+p)mod n+1 (p,q为常整数)之间的区域(连续的一段区域)涂成第i种颜色。

现在由于小Q下达的指令过多,小t一时应付不过来。小Q只让他回答每一个区域最后的颜色。趁小Q还在“五谷轮回之所”忙碌时,小t偷偷的请让你这个计算机高手帮他算出最后的颜色状态,并告诉他。

 

输入格式

文件仅一行,为四个整数n,m,p,q。

 

输出格式

文件共n行,第i行代表最后第i个格子的颜色。白色编号为0。

 

输入样例

4 3 2 4

 

输出样例

2

2

3

0

 

数据范围

20%数据满足:1≤n≤1000,1≤m≤10000;

40%数据满足:1≤n≤10000,1≤m≤100000;

100%数据满足:1≤n≤1000000,1≤m≤10000000;1≤m*p+q,m*q+p≤231-1;

=======================================

开始再为会爆栈而烦恼..在网上找到了个不用栈实现并查集的方法

ORZ...

=================================

var
  n,m,p,q:longint;
  color:array[1..1000000]of longint;
  fa:array[0..1000000]of longint;
  sum:array[0..1000000]of longint;
procedure init;
begin
  assign(input,'paint.in');
  assign(output,'paint.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

function min(a,b:longint):longint;
begin
  if a>b then exit(b);
  exit(a);
end;

function max(a,b:longint):longint;
begin
  if a>b then exit(a);
  exit(b);
end;

function find(x:longint):longint;
var c1,c2:longint;
begin
  c1:=x;
  while c1<>fa[c1] do c1:=fa[c1];
  while x<>fa[x] do begin
                     c2:=fa[x];
                     fa[x]:=c1;
                     x:=c2;
                    end;
  exit(c1);
end;

procedure main;
var
  i,j:longint;
  l,r:longint;
  tem:longint;
  c:longint;
begin
  readln(n,m,p,q);
  fillchar(color,sizeof(color),0);
  for i:=0 to n do fa[i]:=i;
  //赋初始值
  c:=1;
  if m>n then c:=m-n+c;
  for i:=m downto c do
    begin
      l:=(i*p+q)mod n+1;
      r:=(i*q+p)mod n+1;
      if l>r then begin tem:=l; l:=r; r:=tem; end;
      r:=find(r);
      while (l<=r) do
        begin
          if color[r]=0 then begin color[r]:=i; fa[r]:=find(fa[r-1]); r:=fa[r-1]; end
                        else begin fa[r]:=find(fa[r-1]); r:=fa[r-1]; end;
        end;
    end;
  for i:=1 to n do writeln(color[i]);
end;

begin
  init;
  main;
  terminate;
end. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值