现在的位置: 首页 > 综合 > 正文

hdu4391(线段树查找区间内出现的个数)

2018年05月01日 ⁄ 综合 ⁄ 共 2055字 ⁄ 字号 评论关闭
/*
题意:
刷墙, 以开始 有 n个节点,每个节点有一种颜色 ,m 次询问
m次 输入 a,l,r,z 如果 a=1 将 l到 r 刷为 z 颜色,如果 a=2  询问 l 到 r 有 多少个 和 z 相同的 节点
官方题解是: 分段哈希,自己一开始想写 一下 ,单写着写着 就 觉得很麻烦 ,各中判断条件。。。。。
后来改为 线段树  优化了下 ,就是加了 个 mi mx  判断 查询的颜色 是否在这里面。。。。。
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MAX 100010
using namespace std;

//线段树模板
struct line
{
    int left, right; //左端点、右端点
    int c;//color
    int mini, most;
}a[4*MAX];
int v[MAX];

//建立
void build(int s, int t, int n)
{
    int mid = (s + t) / 2;
    a[n].left = s;
    a[n].right = t;
    if (s == t)
    {
        a[n].c = v[s];
        a[n].mini = v[s];
        a[n].most = v[s];
        return;
    }
    build(s, mid, 2 * n);
    build(mid + 1, t, 2 * n + 1);
    if(a[2*n].c == a[2*n+1].c)
        a[n].c = a[2*n].c;
    else
        a[n].c = -1;
    a[n].mini = min(a[2*n].mini, a[2*n+1].mini);
    a[n].most = max(a[2*n].most, a[2*n+1].most);
}
void up(int step)
{
    a[step].mini = min(a[2*step].mini, a[2*step+1].mini);
    a[step].most = max(a[2*step].most, a[2*step+1].most);
    return ;
}
void down(int step)
{
    if(a[step].c != -1)
    {
        a[2*step].c = a[2*step+1].c = a[step].c;
        a[step].c = -1;
        a[2*step].mini = a[2*step+1].mini = a[step].mini;//note
        a[2*step].most = a[2*step+1].most = a[step].most;//note
    }
}
//插入
void modify(int s, int t, int step, int col)
{
    if (s == a[step].left && t == a[step].right)
    {
        a[step].c = col;
        a[step].most = col;
        a[step].mini = col;
        return;
    }
    if (a[step].left == a[step].right)
        return;
    down(step);
    int mid = (a[step].left + a[step].right) / 2;
    if (mid >= t)
        modify(s, t, step * 2, col);
    else if (mid < s)
        modify(s, t, step * 2 + 1, col);
    else
    {
        modify(s, mid, step * 2, col);
        modify(mid + 1, t, step * 2 + 1, col);
    }
    if(a[2*step].c == a[2*step+1].c)
    {
        a[step].c = a[2*step].c;
    }
    up(step);
}
int ans;
void query(int s, int t, int step, int col)
{
    if(a[step].c != -1)//区间的颜色一样
    {
        if(a[step].c == col)//等于查询的颜色
        {
            ans += t - s + 1;
        }
        return;
    }
    if(a[step].left == a[step].right)return;//到底层
    if(a[step].mini > col || a[step].most < col) //重要的优化
        return;
    int mid = (a[step].left + a[step].right) / 2;
    if(mid >= t)
        query(s, t, 2 * step, col);
    else if(mid < s)
        query(s, t, 2 * step + 1, col);
    else
    {
        query(s, mid, 2 * step, col);
        query(mid + 1, t, 2 * step + 1, col);
    }
}

int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        memset(a, 0, sizeof(a));
        int i;
        for(i = 0; i < n; i++)
        {
            scanf("%d", &v[i]);
        };
        build(0, n - 1, 1);
        int flag, lt, rt, col;
        for(i = 1; i <= m; i++)
        {
            scanf("%d%d%d%d", &flag, <, &rt, &col);
            if(flag == 1)
            {
                modify(lt, rt, 1, col);
            }
            else
            {
                ans = 0;
                query(lt, rt, 1, col);
                printf("%d\n", ans);
            }
        }
    }
    return 0;                                                                                     
}

抱歉!评论已关闭.