P2391 白雪皑皑
考察:并查集
并查集维护序列的连通性
Y总在课上提过的题目,本蒟蒻果然不会
思路:
本质是快速染色某个区间.并查集可以帮助我们快速找到第一个未染色的点.
设p[i]为以i为起点第一个需要还未涂色的点(包括i) .通过findf(i)可以帮助我们找到第一个未染色的点.我们在for循环染色[l,r]区间时,i可以直接跳到findf(i)处.这样压缩了染色路径.
一个阅读理解的问题是染色l ~ r之间的点.如果l>r 是swap而不是continue
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int N = 1000010; 6 int n,m,ps,q,p[N],color[N]; 7 int get(int i,int l,int r) 8 { 9 return (i*l+r)%n+1; 10 } 11 int findf(int x) 12 { 13 if(p[x]!=x) p[x] = findf(p[x]); 14 return p[x]; 15 } 16 int main() 17 { 18 scanf("%d%d%d%d",&n,&m,&ps,&q); 19 for(int i=1;i<=n+5;i++) p[i] = i; 20 for(int i=m;i>=1;i--) 21 { 22 int l = get(i,ps,q),r = get(i,q,ps); 23 if(l>r) swap(l,r); 24 l = findf(l); 25 while(l<=r) 26 { 27 color[l] = i; 28 p[l] = findf(l+1); 29 l = findf(l+1); 30 } 31 } 32 for(int i=1;i<=n;i++) 33 printf("%d\n",color[i]); 34 return 0; 35 }