zoukankan      html  css  js  c++  java
  • CF811E(线段树+并查集)

    http://codeforces.com/problemset/problem/811/E
    cf的题面真的是做的美美的,
    所以就直接扔超链接了

    分析:
    线段树的叶子结点维护一列的信息
    包括左右端点,有多少联通块,以及左右两列的并查集情况
    需要注意的是,
    这次代码中的update返回的是一个node
    第一次代码re的原因就是在返回的这个新建的node中
    我没有维护左右端点

    tip

    在update维护左右两列的并查集时,
    这里写图片描述

    这里写图片描述
    (160个点,怀疑人生。。。)

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int N=1e5+7;
    struct node{
        int x,y,l[11],r[11],sum;
    };
    node tree[N<<2];
    int n,m,q,mp[11][N];
    int fa[N*11],tot=0;
    
    int find(int a)
    {
        if (fa[a]!=a) fa[a]=find(fa[a]);
        return fa[a];
    }
    
    node update(int ll,int rr,node lc,node rc,int mid)
    {
        int i;
        node ans;
        ans.x=ll;
        ans.y=rr;
        ans.sum=lc.sum+rc.sum;
        for (i=1;i<=n;i++)
        {
            fa[lc.l[i]]=lc.l[i];
            fa[lc.r[i]]=lc.r[i];
            fa[rc.l[i]]=rc.l[i];
            fa[rc.r[i]]=rc.r[i];
        }
        for (i=1;i<=n;i++)
        {
            if (mp[i][mid]==mp[i][mid+1])
            {
                int f1=find(lc.r[i]);
                int f2=find(rc.l[i]);
                if (f1!=f2)
                {
                    fa[f1]=f2;
                    ans.sum--;
                }
            }
        }
        for (i=1;i<=n;i++)
        {
            ans.l[i]=find(lc.l[i]);  ///
            ans.r[i]=find(rc.r[i]);  ///
        }
        return ans;
    }
    
    void build(int bh,int ll,int rr)
    {
        tree[bh].x=ll;
        tree[bh].y=rr;
        if (ll==rr)
        {
            tree[bh].sum=n;
            for (int i=1;i<=n;i++)
            {
                if (mp[i][ll]==mp[i-1][ll])
                   tree[bh].l[i]=tree[bh].r[i]=tree[bh].l[i-1],tree[bh].sum--;
                else                                                                 
                   tree[bh].l[i]=tree[bh].r[i]=++tot;
            }
            return;
        }
        int mid=(ll+rr)>>1;
        build(bh<<1,ll,mid);
        build(bh<<1|1,mid+1,rr);
        tree[bh]=update(tree[bh].x,tree[bh].y,tree[bh<<1],tree[bh<<1|1],mid);
    }
    
    node ask(int bh,int ll,int rr)
    {
        if (tree[bh].x>=ll&&tree[bh].y<=rr)
        {
            return tree[bh];
        }
        int mid=(tree[bh].x+tree[bh].y)>>1;
        if (rr<=mid) return ask(bh<<1,ll,rr);
        else if (ll>mid) return ask(bh<<1|1,ll,rr);
        else
        {
            return update(ll,rr,ask(bh<<1,ll,rr),ask(bh<<1|1,ll,rr),mid);
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&q);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                scanf("%d",&mp[i][j]);
        tot=0;
        build(1,1,m);
        while (q--)
        {
            int u,w;
            scanf("%d%d",&u,&w);
            node ans=ask(1,u,w);
            printf("%d
    ",ans.sum);
        }
        return 0;
    }
  • 相关阅读:
    html抽取文本信息-java版(适合lucene建立索引)
    【LeetCode with Python】 Sort List
    POJ 2533 Longest Ordered Subsequence(dp LIS)
    Activity 之间 传递 List 封装的对象或者对象
    mongo数据库--非关系型数据库
    cocos2d-x的声音控制
    CSDN博客积分规则
    怎样使用递归实现归并排序
    android中9-patch图片的使用
    Cocos2d-x-3.0环境搭建
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673420.html
Copyright © 2011-2022 走看看