线段树博大精深
对于线段树上的状态压缩, 个人的理解就是把修改的信息转化成二进制存储也不一定是二进制 , 再配上位运算, 来处理问题的一种方法
色板游戏
这一题应该是状态压缩的板子题, 将一段区间内的每个格子涂成某种颜色, 查询某段区间内颜色的种数.
方法1: 将颜色 c c c转化为 2 c 2^{c} 2c来存储, 这样二进制下的每一位1代表1种颜色, 修改的时候直接把这段区间的 d a t a data data修改为 2 c 2^{c} 2c, 延迟标记设为 c c c, 然后向下传递, 查询时只需要将答案转化为二进制, 然后查询二进制下1的个数即可
方法2: 由于颜色种类最多为30, 所以可以建30棵线段树, 每一颗线段树维护一种颜色, 查询时只需要查询每种颜色在这段区间内存不存在即可
XOR on Segment
给你一个n个数的数列, 两种操作, 求出给定区间内数的和, 或者将给定区间内的每个数异或上 x x x.
方法: 建20棵线段树, 每一颗维护二进制下每一位的1的个数.修改时, 根据异或规则修改. 查询时, 查询每一位的1的个数
a n s = ∑ i = 0 20 2 i ∗ q u e r y ans=\displaystyle\sum_{i=0}^{20}2^i*query ans=i=0∑202i∗query
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
#define x first
#define y second
const int MAX_N = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;
//
//
#define int ll
int n, m;
int a[MAX_N], d[21];
struct SegTree {
int l, r;
int dat, lazy;
} tree[21][MAX_N];
inline void push_up(int id, int x) {
tree[id][x].dat = tree[id][x * 2].dat + tree[id][x * 2 + 1].dat;
}
inline void push_down(int id, int x, int ln, int rn) {
if(tree[id][x].lazy) {
tree[id][x * 2].dat = ln - tree