一维黑白棋
一维黑白棋(jdoj-2189)
题目大意:给你一个$1\cdot n$的棋盘,开始都是白色,每次操作是将区间 [ L , R ] 之间的棋子染黑,染m次,求解每次的战况:黑子个数与白子个数。
注释:1<=L<=R<=n<=$2\cdot 10^5$,1<=m<=$2\cdot 10^5$。
想法:这题暴力显然过不去,而且是一个区间修改,区间查询,可以考虑用线段树维护。但是....那不就成傻题了吗!!在此,介绍一种lijinnn神犇讲的做法(博主仅限于听懂)。我们可以考虑用并查集维护:每一个棋子x的father是它右侧第一个白子(包括自己)。那么,维护一个指针,每次修改从L开始,如果是白子,将其染黑,指针++;如果是黑子,指针直接指向它的father,这个黑子的father在指针走了之后修改为R+1,这样就可以在log的时间复杂度内完成修改。这道题就做完了。此题是容易的,但这其中蕴含的是对并查集极其深刻的理解,在此鸣谢lijinnn。
最后,附上帅气的代码(lijinnn在旁指导)......
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int fa[200010]; 5 int find(int x) 6 { 7 if(x==fa[x]) return x; 8 else return fa[x]=find(fa[x]); 9 } 10 int main() 11 { 12 int l,r; 13 int n,m; 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n+1;i++) fa[i]=i; 16 int ans=n; 17 while(m--) 18 { 19 scanf("%d%d",&l,&r); 20 int x=l; 21 while(1) 22 { 23 x=find(x); 24 if(x<=r) 25 { 26 ans--; 27 fa[x]=r+1; 28 x++; 29 } 30 else 31 { 32 printf("%d %d\n",n-ans,ans); 33 break; 34 } 35 } 36 } 37 return 0; 38 }
小结:错误:
1.如果是黑子是,我将它的father设成x+1了,果断Gg
转载请注明:http://www.cnblogs.com/ShuraK/p/7894500.html——未经博主允许,严禁转载
| 欢迎来原网站坐坐! >原文链接<