BZOJ 2054 疯狂的馒头

并查集把染过色的并在一起。倒着染色。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10000050
using namespace std;
int n,m,l[maxn],r[maxn],father[maxn/10],p,q,col[maxn/10];
int getfather(int x)
{
    if (x!=father[x]) father[x]=getfather(father[x]);
    return father[x];
}
void unionn(int x,int y)
{
    if ((!col[x]) && (!col[y])) return;
    int f1=getfather(x),f2=getfather(y);
    father[f1]=f2;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&p,&q);
    for (int i=1;i<=m;i++)
    {
        l[i]=(i*p+q)%n+1;r[i]=(i*q+p)%n+1;
        if (l[i]>r[i]) swap(l[i],r[i]);
    }
    for (int i=1;i<=n;i++) father[i]=i;
    for (int i=m;i>=1;i--)
    {
        int now=l[i];
        if (col[now]) now=getfather(now)+1;
        while (now<=r[i])
        {
            unionn(now-1,now);unionn(now,now+1);
            col[now]=i;
            now++;
            if (col[now]) now=getfather(now)+1;
        }
    }
    for (int i=1;i<=n;i++) printf("%d\n",col[i]);
    return 0;
}
时间: 2024-12-17 16:55:35

BZOJ 2054 疯狂的馒头的相关文章

BZOJ 2054 疯狂的馒头 并查集

题目大意:给定一个序列,多次将某个区间染成某种颜色,求最后每个点是什么颜色 m<=1000W,线段树肯定T 由于对每个点起作用的染色只有最后一次,因此倒着做,如果一个点已经被染色,就在并查集中将这个点连向右面那个 这样每个点只会被染色一次,时间复杂度O(n+m) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1001001

Bzoj P2054 疯狂的馒头 | 并查集

题目链接 思路:因为每次染色都会将某些馒头的颜色彻底更改,所以每个馒头的最终的颜色其实是由最后一次染色决定的,那么我们只考虑最后一次染色即可.对此,我们可以从后往前倒着染色,当目前的染色区间中存在白色馒头时,就将其染成当前的颜色,对于已经染过色的馒头则不处理,因为当前这一次染色已经不是其最后一次染色了,其最终颜色已经确定了. 对以上思路,考虑用经过路径压缩优化的并查集来维护在每个馒头右侧的.距离最近的.未染色的馒头的位置,以减小时间复杂度. 总时间复杂度O(m+n). 代码: #include<

(区间操作) bzoj 2054

2054: 疯狂的馒头 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 449  Solved: 175[Submit][Status] Description Input 第一行四个正整数N,M,p,q Output 一共输出N行,第i行表示第i个馒头的最终颜色(如果最终颜色是白色就输出0). Sample Input 4 3 2 4 Sample Output 2 2 3 0 HINT 用并查集搞啊啊啊啊啊啊啊啊啊啊啊啊 #include<io

BZOJ2054 疯狂的馒头

还是离线把操作倒过来做,于是每个馒头只要看最后一种颜色就好了 如果一个馒头已经有颜色了,就把它并到右边的馒头的集合里去 1 /************************************************************** 2 Problem: 2054 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:3268 ms 7 Memory:39776 kb 8 ***********************

【BZOJ2054】疯狂的馒头(并查集)

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2054 水题QAQ, 并查集就可以了. 1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #define LL long long 5 #define MaxN 1000010 6 using namespace std; 7 int n, m, q, p, S = 0; 8 int an

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) 代码

bzoj 2375: 疯狂的涂色

2375: 疯狂的涂色 Time Limit: 5 Sec  Memory Limit: 128 MB Description 小t非常喜爱画画,但是他还是一个初学者.他最近费尽千辛万苦才拜到已仙逝的达芬奇为师(神仙?妖怪?谢谢).达芬奇果然是画鸡蛋长大的,让小t一入门就拿着一张白纸条疯狂地涂色.假设纸条被划分成了n个区域,用1~n的整数从左到右顺序编号,达芬奇总共下达了m条指令.第I条指令是让小t把编号为(I*p+q)mod n+1与(I*q+p)mod n+1(p,q为常整数)之间的区域(连

Crash的数字表格(bzoj 2054)

Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数.例如,LCM(6, 8) = 24.回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格.每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j).一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12

Noip前的大抱佛脚----数据结构

数据结构 线段树 注意:空间开4倍 神奇标记 From8.26 Test_zsy(CPU监控) 如果一个点权为\(val\)的点被打上了\((a,b)\)标记,那么他的实际点权为\(max(a+val,b)\) 干啥滴? 标记不下放 区间加标记不下放,维护区间max或者最大值 方法是当前\(tag\)维护当前区域标记,\(t\)维护左右儿子的\(max+tag[now]\),并没有快多少,如果仍然忘记见提交记录 并查集 维护二分图 并查集每个点维护是否要改颜色,然后按秩合并/按大小合并即可 实际