/*
题意:
刷墙, 以开始 有 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;
}
hdu4391(线段树查找区间内出现的个数)
最新推荐文章于 2021-11-15 22:13:06 发布