一维黑白棋

一维黑白棋(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——未经博主允许,严禁转载

posted @ 2017-11-25 09:52  JZYshuraK_彧  阅读(406)  评论(0编辑  收藏  举报