BOZJ 2045:疯狂的馒头(并查集)

题目大意:有n个馒头排成一排,初始时颜色为0,进行m次染色,第i次将(i*p+q)mod n到(i*q+p)mod n的馒头全部染成颜色i,求最后所有馒头颜色。n<=10^6 m<=10^7

分析:nm很大不能线段树,可以考虑用并查集,我们发现每个馒头可能会被染色多次,但只有最后一次染色能决定它的最终颜色,故倒着做,并且使每个点颜色只修改一次,对于区间[x,y],从x开始将除以外的点父亲全部指向下一个,这样这个区间全部指向了y,下一次修改时会跳过该区间,由于只会修改n个点故效率为O(n)

代码:

program asfd;
var
  a:array[0..1000001]of longint;
  f:array[0..1000001]of longint;
  n,i,m,p,q,k,x,y,t,j:longint;
function find(x:longint):longint;
var i,j,k:longint;
begin
  i:=x; j:=x;
  while i<>f[i] do i:=f[i];
  while i<>j do
   begin
     k:=f[j]; f[j]:=i; j:=k;
   end;
  exit(i);
end;
begin
  readln(n,m,p,q);
  for i:=1 to n do f[i]:=i; k:=0;
  for i:=m downto 1 do
   begin
     x:=(i*p mod n+q)mod n+1;
     y:=(i*q mod n+p)mod n+1;
     if x>y then begin t:=x; x:=y; y:=t; end;
     j:=find(x);
     while j<=y do
      begin
        a[j]:=i; f[j]:=j+1; inc(k);
        if k=n then break;
        j:=find(j);
      end;
   end;
  for i:=1 to n do
   writeln(a[i]);
  readln;
end.
View Code

 

转载于:https://www.cnblogs.com/qtyytq/p/6058689.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值