首页 > 其他分享 >洛谷P1558 色板游戏 题解

洛谷P1558 色板游戏 题解

时间:2022-09-04 00:11:06浏览次数:59  
标签:return int 题解 top 色板 read Ge P1558 col

高考完后随机跳题的复建运动。

看到区间覆盖操作考虑线段树。

30种颜色?用位运算存储节省空间。因为在线段树上传合并时只需要考虑这一段是否存在该颜色,(即\(0\)或\(1\))具体位置和长度都不用考虑。(以下简称为“颜料桶”)

\(pushup\)操作:直接暴力30种颜色对比两个儿子,记录下颜色存在状况以及当前颜色数量。

\(pushdown\):已知,向下推的标记一定都是全区间覆盖为同一种颜色,因此全部刷新,颜料桶刷为仅一种颜色,数量当然也是\(1\)。

为了方便,这里使用了结构体上下传。
具体细节看代码吧。

/*
author: Blue_Bird
2022.9.3
*/

#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long

template <class T>
inline void read(T& a){
	T x = 0, s = 1;
	char c = getchar();
	while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
	a = x * s;
	return ;
}

int n, cnum, q; 

struct Ge{
	int col;  // 上传当前颜色
	int ans;  
	
	Ge operator + (const Ge& a) const{
		Ge temp = (Ge){0, 0};
		int num = 0; 
		temp.col |= col; temp.col |= a.col;
		for(int i = 1; i <= cnum; i++){  // 比较颜色位置 
			if((col & (1 << i)) || (a.col & (1 << i))){
				num++; 
				 
			}  // 存在这个颜色 
		}
		temp.ans = num;
		return temp; 	
	}
} ;

struct Segment_tree{
	struct node{
		ll top;   // 位运算装颜色
		int col;   // 纯色块 
		int w; 
		
		node(){
			this->col = 0;
			this->top = 0; 
			return ; 
		}
		
	} t[N << 2];
	
	#define lson o<<1
	#define rson o<<1|1
	
	int temp = 0;  
	
	inline void pushup(int o){    //   *************此处可以优化    两边为纯色块时不需要循环判断 
		this->temp = 0; 
		for(int i = 1; i <= cnum; i++){  // 比较颜色位置 
			if((t[lson].top & (1 << i)) || (t[rson].top & (1 << i)))  // 存在这个颜色 
				this->temp += 1; 
		}
		t[o].top = 0; // 清空之前的 
		t[o].top |= t[lson].top; t[o].top |= t[rson].top;   // 两边的颜色类型合并 
		t[o].w = this->temp; 
		return ;
	}
	
	inline void pushdown(int o, int l, int r){  // 下推标记 
		if(!t[o].col) return ; 		  // 无修改 
		t[lson].col = t[o].col; t[rson].col = t[o].col; // 向下刷色 
		
		t[lson].w = t[rson].w = 1; 
		
		t[lson].top = t[rson].top = 0;     // 刷成纯色 
		t[lson].top |= (1 << t[o].col); t[rson].top |= (1 << t[o].col);   
		
		
		t[o].col = 0;    // 清空 
		return ;  
	} 
	
	void build(int o, int l, int r){
		if(l == r){
			t[o].top |= (1 << 1);   // 一号颜色为真 
			t[o].col = 1;  // 纯色块颜色为 1
			t[o].w = 1; 
			return ;  
		}
		int mid = l + r >> 1;
		build(lson, l, mid); build(rson, mid + 1, r);  
		pushup(o); 
		return ; 
	}
	
	void update(int o, int l, int r, int in, int end, int k){  // k: 修改的颜色 
		if(l > end || r < in) return ;
		if(l >= in && r <= end){  // 在刷纯色区间内 
			t[o].col = k;
			t[o].top = 0; t[o].top |= (1 << k); 
			t[o].w = 1; 
			return ; 
		}
		pushdown(o, l, r); 
		int mid = l + r >> 1;
		update(lson, l, mid, in, end, k); 
		update(rson, mid + 1, r, in, end, k);
		pushup(o);
		return ; 
	}
	
	Ge query(int o, int l, int r, int in, int end){
		if(l > end || r < in) return (Ge){0, 0}; 
		if(l >= in && r <= end){
			return (Ge){t[o].top, t[o].w}; 
		}
		pushdown(o, l, r);
		int mid = l + r >> 1;
		Ge t1, t2; 
		Ge temp = query(lson, l, mid, in, end) + query(rson, mid + 1, r, in, end); 
		return temp;  
	}	
} tree;

int main(){
//	freopen("hh.txt", "r", stdin); 
	read(n), read(cnum), read(q);
	tree.build(1, 1, n); 
	
	while(q--){
		char opt; int x, y, z, ans; 
		cin >> opt;
		switch(opt){
			case ('C'):
				read(x), read(y), read(z);
				if(x > y) swap(x, y); 
				tree.update(1, 1, n, x, y, z); 
				break; 
			case ('P'):
				read(x), read(y);
				if(x > y) swap(x, y); 
				Ge ans = tree.query(1, 1, n, x, y) ;
				printf("%d\n", ans.ans); 
				break; 
		}
	}
	
	return 0;
}


标签:return,int,题解,top,色板,read,Ge,P1558,col
From: https://www.cnblogs.com/wondering-world/p/16654046.html

相关文章

  • AGC010F 题解
    现在也就会写一写代码长度不超过\(1k\)的题目了。/kk看上去一脸不可做,看到从必败状态逆推的提示后会了。考虑什么算是必败状态,我们设此时棋子所在的位置为\(now\)......
  • 攻防世界 pwn1 题解
    攻防世界pwn1题解下载附件,file命令识别文件为64位,checksec命令查看程序保护情况,如图,有Canary和NX保护。在ida64中打开程序,程序的主要功能有两个:存储用户输入的字符......
  • 9.3 noip 模拟赛 1 题解
    noip模拟赛1题解目录noip模拟赛1题解\(\tolink\leftarrow\)A一步之遥退位计划退役以后重在参与\(\tolink\leftarrow\)A一步之遥构造题手玩了一下没有什么......
  • ARC146 部分题解
    A普及组题//byBalloons#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#definemprmake_pair#definedebug()cerr<<"Madoka"<<e......
  • P5914 [POI2004]MOS 题解
    题目传送门分析这是一道小学经典的数学题,对于这种求最短时间的题目,我们要认真考虑两组人员:首先,跑的快的人应当跑的最多,能者多劳。其次,跑的慢的人应当跑的最少,否则会拉......
  • CF1389B题解
    题目传送门题目分析首先,这道题比较的简单,是一道较为标准的dp,虽说有大佬说可以用贪心做,但本蒟蒻不会。首先,\(0\leqz\leq\min(5,k)\)所以我们可以开一个二维dp,......
  • 【题解】「COCI 2018.10」Teoretičar
    传送门题目大意有一个二分图,构造一种对边的染色方案,使得没有两个颜色相同的边共顶点。假设对于给定二分图的答案是\(C\),记\(X\)是大于等于\(C\)的最小的\(2\)的......
  • 「题解」Longge 的问题
    原题目链接:Link。虽然已经被A穿了但还是写一下。\[\sum_{i=1}^n\gcd(i,n)=\sum_{d\vertn}\sum_{i=1}^n[\gcd(i,n)=d]\]这一步显然,因为\(\forall\gc......
  • P2858 [USACO06FEB]Treats for the Cows G/S 题解
    [USACO06FEB]TreatsfortheCowsG/S[USACO06FEB]TreatsfortheCowsG/S题目描述FJhaspurchasedN(1<=N<=2000)yummytreatsforthecowswhogetmoneyfo......
  • P1005 [NOIP2007 提高组] 矩阵取数游戏 题解
    luogu原题传送门[NOIP2007提高组]矩阵取数游戏题目描述帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(n\timesm\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非......