zoukankan      html  css  js  c++  java
  • hdu4638

    hdu4638

    题意

    给定一个序列,序列由1-N个元素全排列而成,求任意区间可组成的连续的段数,比如[1,2,4]两段{[1,2],[4]},[1,2,4,3]一段{[1,2,3,4]}。
    对于查询的区间询问的是可组成的连续的数的段数最小值。

    分析

    分块排好序,O(1)的维护就是每新添加一个元素 t 查看 t-1 与 t+1 是否都在区间内,如是则段数-1,如果都不在,则段数+1。

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN = 1e5 + 10;
    int a[MAXN];
    int vis[MAXN];
    int ans[MAXN];
    struct node
    {
        int l, r, bid, id;
        bool operator < (const node &other) const
        {
            if(bid == other.bid) return r < other.r;
            return bid < other.bid;
        }
    }q[MAXN];
    
    int L, R, res;
    
    void query(int l, int r, int is)
    {
        if(is)
        {
            for(int i = l; i < L; i++)
            {
                if(vis[a[i] - 1] && vis[a[i] + 1]) res--;
                else if(!vis[a[i] - 1] && !vis[a[i] + 1]) res++;
                vis[a[i]] = 1;
            }
            for(int i = R + 1; i <= r; i++)
            {
                if(vis[a[i] - 1] && vis[a[i] + 1]) res--;
                else if(!vis[a[i] - 1] && !vis[a[i] + 1]) res++;
                vis[a[i]] = 1;
            }
            for(int i = L; i < l; i++)
            {
                if(vis[a[i] - 1] && vis[a[i] + 1]) res++;
                else if(!vis[a[i] - 1] && !vis[a[i] + 1]) res--;
                vis[a[i]] = 0;
            }
            for(int i = r + 1; i <= R; i++)
            {
                if(vis[a[i] - 1] && vis[a[i] + 1]) res++;
                else if(!vis[a[i] - 1] && !vis[a[i] + 1]) res--;
                vis[a[i]] = 0;
            }
        }
        else
        {
            for(int i = l; i <= r; i++)
            {
                if(vis[a[i] - 1] && vis[a[i] + 1]) res--;
                else if(!vis[a[i] - 1] && !vis[a[i] + 1]) res++;
                vis[a[i]] = 1;
            }
        }
        L = l; R = r;
        ans[q[is].id] = res;
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            int n, m;
            memset(vis, 0, sizeof vis);
            res = 0;
            scanf("%d%d", &n, &m);
            int bsize = sqrt(n);
            for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
            for(int i = 0; i < m; i++)
            {
                scanf("%d%d", &q[i].l, &q[i].r);
                q[i].id = i;
                q[i].bid = q[i].l / bsize;
            }
            sort(q, q + m);
            for(int i = 0; i < m; i++) query(q[i].l, q[i].r, i);
            for(int i = 0; i < m; i++) printf("%d
    ", ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    12-五子棋游戏:享元模式
    11-制作糖醋排骨:外观模式
    10-蒸馒头:装饰者模式
    09-公司层级结构:组合模式
    08-开关与电灯:桥接模式
    07-电源转换:适配器模式
    将博客搬至CSDN
    iview和element中日期选择器快捷选项的定制控件
    详解AJAX工作原理以及实例讲解(通俗易懂)
    最全肌肉锻炼动图
  • 原文地址:https://www.cnblogs.com/ftae/p/6791395.html
Copyright © 2011-2022 走看看