[luogu P2391] 白雪皑皑
题目背景
“柴门闻犬吠,风雪夜归人”,冬天,不期而至。千里冰封,万里雪飘。空中刮起了鸭毛大雪。雪花纷纷,降落人间。 美能量星球(pty 在 spore 上的一个殖民地)上的人们被这美景所震撼。但是 pty 却不高兴,他不喜欢白色的世界,他觉得这样太单调了。所以他想对雪花进行染色,让世界变得多彩些。
题目描述
现在有 N 片雪花排成一列。 Pty 要对雪花进行 M 次染色操作,第 i次染色操作中,把第(i*p+q)%N+1 片雪花和第(i*q+p)%N+1 片雪花之间的雪花(包括端点)染成颜色 i。其中 p,q 是给定的两个正整数。他想知道最后 N 片雪花被染成了什么颜色。
输入输出格式
输入格式:
包含 4 行:
N M p q 意义如题中所述。
输出格式:
包含 N 行:
第 i 行表示第 i 片雪花被染成的颜色 c
输入输出样例
说明
20%的数据满足:1<=n,m<=1000
40%的数据满足:1<=n<=8000,1<=m<=1000000
80%的数据满足:1<=n<=500000,1<=m<=10000000
100%的数据满足:1<=n<=1000000,1<=m<=10000000
保证 1<=M*p+q,M*q+p<=2*10^9
脑子都不好使了。。。并查集都用不来了。
对于这一题,我们可以把原问题转为做m次修改。
每一次修改,在一个区间内,把没有修改过的位置染上色(即修改)。
然后,最后输出每一个位置分别是哪一种颜色(即哪次修改,也可能为0,表示没有修改)。
妙用并查集,有点链表的味道,用fa[i]表示1~i里面,离i最近的没有被修改过的位置。
然后,对于一次修改,把当前位置修改好了就修改fa[i],一直到修改好为止(或是修改到0)。
由于每个位置最多被修改1次,所以复杂度是O(n)的。最多乘上一个并查集常数。
有个地方还需要探讨一下——就是路径压缩的问题。
对于这题,路径压缩之后有没有影响?
不存在的。我们可以吧点于点的关系看做是树,森林。
那么,事实上,只有根节点才没有被修改过,其他点都是已经修改过的,所以无论关系怎么变化,都不会有影响。
当然,运用并查集就是为了增快查询速度,而且路径压缩是关键。
注意,在更新fa[i]时,直接取i-1或fa[i-1]或get(i-1)就好,因为i这个位置被访问到当且仅当它第一次被更新到。
那么这样,根据定义,fa[i]就是get(i-1)了。
code:
View Code1 #pragma GCC optimize(2) 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long LL; 6 namespace fastIO { 7 inline int read() { 8 int x=0,f=1; char ch=getchar(); 9 while (ch<'0'||ch>'9') { 10 if (ch=='-') f=-f; 11 ch=getchar(); 12 } 13 while (ch>='0'&&ch<='9') { 14 x=(x<<3)+(x<<1)+ch-'0'; 15 ch=getchar(); 16 } 17 return x*f; 18 } 19 int cnt,w[20]; 20 inline void write(int x) { 21 if (x==0) { 22 putchar('0'); 23 return; 24 } 25 if (x<0) { 26 x=-x; 27 putchar('-'); 28 } 29 for (cnt=0; x; x/=10) w[++cnt]=x%10; 30 for (; cnt; --cnt) putchar(w[cnt]+48); 31 } 32 inline void newline() { 33 putchar('\n'); 34 } 35 } 36 namespace OJ{ 37 void Online_Judge() { 38 #ifndef ONLINE_JUDGE 39 freopen("in.txt","r",stdin); 40 freopen("out.txt","w",stdout); 41 #endif 42 } 43 } 44 const int N=1000005; 45 int n,m,p,q,fa[N],cov[N]; 46 inline int get(int x) { 47 return fa[x]==x?x:fa[x]=get(fa[x]); 48 } 49 int main() { 50 OJ::Online_Judge(); 51 using namespace fastIO; 52 n=read(),m=read(),p=read(),q=read(); 53 for (int i=1; i<=n; ++i) { 54 cov[i]=0; 55 fa[i]=i; 56 } 57 int l,r; 58 for (int i=m; i; --i) { 59 l=(i*p+q)%n+1,r=(i*q+p)%n+1; 60 if (l>r) std::swap(l,r); 61 for (r=get(r); l<=r; r=get(r)) { 62 cov[r]=i; 63 fa[r]=r-1; 64 } 65 } 66 for (int i=1; i<=n; ++i) { 67 write(cov[i]); 68 newline(); 69 } 70 return 0; 71 }
本文介绍了一个使用并查集算法解决雪花染色问题的方法。在一个由N片雪花构成的序列中,通过M次染色操作,将特定范围内的雪花染成不同颜色。文章详细解释了如何利用并查集优化查询过程,实现高效的颜色分配。


108

被折叠的 条评论
为什么被折叠?



