P1558 维护多棵线段树

色板游戏

题目背景

阿宝上学了,今天老师拿来了一块很长的涂色板。

题目描述

色板长度为 \(L\)\(L\) 是一个正整数,所以我们可以均匀地将它划分成 \(L\)\(1\) 厘米长的小方格。并从左到右标记为 \(1, 2, \dots L\)

现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:

  1. C A B C 指在 \(A\)\(B\) 号方格中涂上颜色 \(C\)
  2. P A B 指老师的提问:\(A\)\(B\) 号方格中有几种颜色。

学校的颜料盒中一共有 \(T\) 种颜料。为简便起见,我们把他们标记为 \(1, 2, \dots T\). 开始时色板上原有的颜色就为 \(1\) 号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?

输入格式

第一行有3个整数 \(L (1 \le L \le 10^5), T (1 \le T \le 30) 和 O (1 \le O \le 10^5)\)。 在这里 \(O\) 表示事件数。

接下来 \(O\) 行, 每行以 C A B CP A B 得形式表示所要做的事情(这里 \(A, B, C\) 为整数, 可能 \(A> B\),这样的话需要你交换 \(A\)\(B\))。

输出格式

对于老师的提问,做出相应的回答。每行一个整数。

样例 #1

样例输入 #1

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

样例输出 #1

2
1

暴力思路:建30棵线段树 维护每个区间上的颜色

以后可以这种方法“骗分”!!!

我是采用维护 maxx 如果 tr[id][p].maxx>0说明id这种颜色有

注意一个点 我们bj是 -1 0 1 -1代表标记清除! 由于 这道题 0/1 有特殊含义 所以不能像普通懒标记那样 用 0来代表清除

至于最后一个点嘛 这种写法就是 用空间换取了简便写法 要卡过去的话要将 tr中维护的l r 在每个函数中带上 也就是 只有 tr[id][p].maxx 和 tr[id][p].bj 这种才能将空间卡过去

当然 已经足够了(本来就没强求AC)

#include<bits/stdc++.h>
using namespace std;
const int N=6e4+5;
int n,t,o;
struct SegTree {
	int l,r,maxx,bj=-1;//-1   0    1
} tr[31][N<<2];
void pushup(int id,int p) {
	tr[id][p].maxx=max(tr[id][p<<1].maxx,tr[id][p<<1|1].maxx);
}
void pushdown(int id,int p) {
	if(tr[id][p].bj==-1)return ;
	tr[id][p<<1].maxx=tr[id][p].bj;
	tr[id][p<<1|1].maxx=tr[id][p].bj;
	tr[id][p<<1].bj=tr[id][p].bj;
	tr[id][p<<1|1].bj=tr[id][p].bj;
	tr[id][p].bj=-1;
}
void build(int id,int p,int l,int r,int k) {
	tr[id][p].l=l,tr[id][p].r=r;
	if(l==r) {
		tr[id][p].maxx=k;
		return ;
	}
	int mid=(l+r)>>1;
	build(id,p<<1,l,mid,k);
	build(id,p<<1|1,mid+1,r,k);
	pushup(id,p);
}
void modify(int id,int p,int l,int r,int k) {
	if(l<=tr[id][p].l&&r>=tr[id][p].r) {
		tr[id][p].bj=k;
		tr[id][p].maxx=k;
		return ;
	}
	pushdown(id,p);
	int mid=(tr[id][p].l+tr[id][p].r)>>1;
	if(l<=mid)modify(id,p<<1,l,r,k);
	if(r>mid)modify(id,p<<1|1,l,r,k);
	pushup(id,p);
}
int query(int id,int p,int l,int r) {
	int maxx=-1;
	if(l<=tr[id][p].l&&r>=tr[id][p].r)return tr[id][p].maxx;
	pushdown(id,p);
	int mid=(tr[id][p].l+tr[id][p].r)>>1;
	if(l<=mid)maxx=max(maxx,query(id,p<<1,l,r));
	if(r>mid)maxx=max(maxx,query(id,p<<1|1,l,r));
	return maxx;
}
signed main() {
	ios::sync_with_stdio(false);
	cin>>n>>t>>o;
	build(1,1,1,n,1);
	for(int i=2; i<=t; i++)build(i,1,1,n,0);
	while(o--) {
		char op;
		int a,b,c;
		cin>>op;
		if(op=='C') {
			cin>>a>>b>>c;
			if(a>b)swap(a,b);
			modify(c,1,a,b,1);
			for(int i=1; i<=t; i++)
				if(i!=c)
					modify(i,1,a,b,0);
		}
		if(op=='P') {
			cin>>a>>b;
			if(a>b)swap(a,b);
			int ans=0;
			for(int i=1; i<=t; i++)
				if(query(i,1,a,b)>0)
					ans++;
			cout<<ans<<"\n";
		}
	}
	return 0;
}

优化空间AC版

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,t,o;
struct SegTree {
	int maxx,bj=-1;//-1   0    1
} tr[31][N<<2];
void pushup(int id,int p) {
	tr[id][p].maxx=max(tr[id][p<<1].maxx,tr[id][p<<1|1].maxx);
}
void pushdown(int id,int p) {
	if(tr[id][p].bj==-1)return ;
	tr[id][p<<1].maxx=tr[id][p].bj;
	tr[id][p<<1|1].maxx=tr[id][p].bj;
	tr[id][p<<1].bj=tr[id][p].bj;
	tr[id][p<<1|1].bj=tr[id][p].bj;
	tr[id][p].bj=-1;
}
void build(int id,int p,int l,int r,int k) {
	if(l==r) {
		tr[id][p].maxx=k;
		return ;
	}
	int mid=(l+r)>>1;
	build(id,p<<1,l,mid,k);
	build(id,p<<1|1,mid+1,r,k);
	pushup(id,p);
}
void modify(int id,int p,int l,int r,int L,int R,int k) {
	if(l>R||r<L)return ;
	if(L<=l&&R>=r) {
		tr[id][p].bj=k;
		tr[id][p].maxx=k;
		return ;
	}
	pushdown(id,p);
	int mid=(l+r)>>1;
	if(L<=mid)modify(id,p<<1,l,mid,L,R,k);
	if(R>mid)modify(id,p<<1|1,mid+1,r,L,R,k);
	pushup(id,p);
}
int query(int id,int p,int l,int r,int L,int R) {
	int maxx=-1;
	if(l>R||r<L)return 0;
	if(L<=l&&R>=r)return tr[id][p].maxx;
	pushdown(id,p);
	int mid=(l+r)>>1;
	if(L<=mid)maxx=max(maxx,query(id,p<<1,l,mid,L,R));
	if(R>mid)maxx=max(maxx,query(id,p<<1|1,mid+1,r,L,R));
	return maxx;
}
signed main() {
	ios::sync_with_stdio(false);
	cin>>n>>t>>o;
	build(1,1,1,n,1);
	for(int i=2; i<=t; i++)build(i,1,1,n,0);
	while(o--) {
		char op;
		int a,b,c;
		cin>>op;
		if(op=='C') {
			cin>>a>>b>>c;
			if(a>b)swap(a,b);
			modify(c,1,1,n,a,b,1);
			for(int i=1; i<=t; i++)
				if(i!=c)
					modify(i,1,1,n,a,b,0);
		}
		if(op=='P') {
			cin>>a>>b;
			if(a>b)swap(a,b);
			int ans=0;
			for(int i=1; i<=t; i++)
				if(query(i,1,1,n,a,b)>0)
					ans++;
			cout<<ans<<"\n";
		}
	}
	return 0;
}
posted @ 2023-04-30 17:39  N0zoM1z0  阅读(3)  评论(0编辑  收藏  举报