Jzoj P4603 颜料大乱斗___线段树+状态压缩

题目大意:

n n 个板砖,按序排列以及编号,颜色初始时都为 1 1 ,有 c c 种颜色,也是从 1 1 c c 编号, m m 个询问,
每个询问可以支持两种操作:
( C , x , y , z ) (C,x,y,z) 将第 x x 个板砖到第 y y 个板砖的颜色变成 z z
( P , x , y ) (P,x,y) 问第 x x 个板砖到第 y y 个板砖有多少种颜色在这里插入图片描述

分析:

线段树处理,
每个节点用一个数去记录一下这个结点代表的区间有多少种颜色,因为颜色种类很少
然后就是正常的区间修改,注意修改的时候打lazy即可
然后查询的时候的 l , r l,r 可能 l > r l>r ,这时候不合法要交换顺序(坑)
然后回答区间颜色种类的时候就是找到对应区间的状态 或起来以后即为答案
注意某个区间只有一种颜色就直接返回该区间的状态即可,因为它所有的子区间都是只有这种颜色

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>

#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define lson(x) x * 2
#define rson(x) x * 2 + 1
#define der(x) 1 << x

#define N 100005

using namespace std;

struct Node { int lzy, tot; }a[N*5];
int n, m, q, ans;


void Update(int x)
{
	a[x].tot = a[lson(x)].tot | a[rson(x)].tot;
}

void pushdown(int x)
{
	if (a[x].lzy != -1) { a[lson(x)].tot = a[rson(x)].tot = der(a[x].lzy), a[lson(x)].lzy = a[rson(x)].lzy = a[x].lzy; a[x].lzy = -1; }
}

int Get_num(int x)
{
	int num = 0;
	for (; x; x >>= 1) num = num + (x & 1 ? 1 : 0);
	return num;
}

void Build(int G, int l, int r)
{
	a[G].tot = 1; a[G].lzy = -1;
	if (l == r) return;  
	int mid = (l + r) >> 1;
	Build(lson(G), l, mid);
	Build(rson(G), mid + 1, r);
}

void change(int G, int l, int r, int liml, int limr, int cnum)
{
	if (l == liml && r == limr) { a[G].tot = der(cnum), a[G].lzy = cnum; return; }
    int mid = (l + r) >> 1;
    pushdown(G);
    if (limr <= mid) change(lson(G), l, mid, liml, limr, cnum);
	   else if (liml > mid) change(rson(G), mid + 1, r, liml, limr, cnum);
	           else change(lson(G), l, mid, liml, mid, cnum), change(rson(G), mid + 1, r, mid + 1, limr, cnum);
	Update(G); 
}

void query(int G, int l, int r, int liml, int limr)
{
	if (Get_num(a[G].tot) == 1) { ans = ans | a[G].tot; return; } 
	if (l == liml && r == limr) { ans = ans | a[G].tot; return; }
	int mid = (l + r) >> 1;
	pushdown(G);
	if (limr <= mid) query(lson(G), l, mid, liml, limr);
	   else if (liml > mid) query(rson(G), mid + 1, r, liml, limr);
	           else query(lson(G), l, mid, liml, mid), query(rson(G), mid + 1, r, mid + 1, limr);
    Update(G);
}

void Get_Answer(int l, int r)
{
	ans = 0;
	query(1, 1, n, l, r);
	printf("%d\n", Get_num(ans)); 
}

int main()
{
	scanf("%d %d %d", &n, &m, &q);
	Build(1, 1, n);
	char opt[2]; int l, r, x;
	rep(i, 1, q)
	{
	    scanf("%s %d %d", opt, &l, &r);	
	    if (l > r) swap(l, r);
	    if (opt[0] == 'C')  { scanf("%d", &x); change(1, 1, n, l, r, x - 1); }
	       else if (opt[0] == 'P') Get_Answer(l, r); 
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Gx_Man_VIP/article/details/92394682
今日推荐