【模板】线段树(&离散化)
适用于区间染色及查询颜色段数
#include <stdio.h>
using namespace std;
template<int the_size>
class SEGMENT_TREE {
private :
struct SEGMENT {
int part;
int keyl, keyr;
SEGMENT() {part = 0; keyl = keyr = -1; }
} seg[the_size<<2];
int boarder, *temp;
#define lid(id) id<<1|1
#define rid(id) id<<1
#define part(id) seg[id].part
#define l(id) seg[id].keyl
#define r(id) seg[id].keyr
void update(int id) {
l(id) = l(lid(id));
r(id) = r(rid(id));
part(id) = part(lid(id))+part(rid(id))-(r(lid(id)) == l(rid(id)));
}
void download(int id) {
if(part(id) == 1) {
l(lid(id)) = r(lid(id)) = l(id);
l(rid(id)) = r(rid(id)) = r(id);
part(lid(id)) = part(rid(id)) = 1;
}
}
int get_part(int id,int L,int R,int l,int r) {
if(L > r||R < l)
return 0;
if(L >= l&&R <= r)
return part(id);
download(id);
int mid = (L+R)>>1;
return get_part(lid(id),L,mid,l,r)+get_part(rid(id),mid+1,R,l,r);
}
void change(int id,int L,int R,int l,int r,int col) {
if(L > r||R < l)
return;
if(L >= l&&R <= r) {
part(id) = 1;
l(id) = r(id) = col;
return;
}
int mid = (L+R)>>1;
change(lid(id),L,mid,l,r,col);
change(rid(id),mid+1,R,l,r,col);
update(id);
}
void build(int id,int L,int R) {
if(L == R) {
part(id) = 1;
l(id) = r(id) = temp[L];
return;
}
int mid = (L+R)>>1;
build(lid(id),L,mid);
build(rid(id),mid+1,R);
update(id);
}
#undef l
#undef r
#undef part
#undef lid
#undef rid
public :
int query(int l,int r) {
return get_part(1,1,boarder,l,r);
}
void revise(int l,int r,int col) {
change(1,1,boarder,l,r,col);
}
void construct(int *col,int size) {
boarder = size;
temp = col;
build(1,1,boarder);
}
};
SEGMENT_TREE<1024> st;
signed main() {
int a[1024], n, m;
scanf("%d",&n);
for(int i = 1;i <= n;++i)
scanf("%d",&a[i]);
st.construct(a,n);
scanf("%d",&m);
for(int i = 1, opt;i <= n;++i) {
scanf("%d",&opt);
int l, r, c;
if(opt == 1) {
scanf("%d %d",&l,&r);
printf("%d\n",st.query(l,r));
} else {
scanf("%d %d %d",&l,&r,&c);
st.revise(l,r,c);
}
}
}
点击查看代码
#include <stdio.h>
template <int the_size,typename Tec>
class SEGMENT_TREE {
private :
struct SEGNODE {
Tec sumn, maxn;
Tec tag, lazy;
SEGNODE () {lazy = sumn = 0, maxn = -998244353, tag = -1;}
} segnode[the_size << 2];
Tec *given;
int boarder;
#define lid(id) id<<1|1
#define rid(id) id<<1
#define sumn(id) segnode[id].sumn
#define maxn(id) segnode[id].maxn
#define tag(id) segnode[id].tag
#define lazy(id) segnode[id].lazy
template<typename TecInner>
TecInner max(TecInner __x,TecInner __y) {
return __x > __y ? __x : __y;
}
template<typename TecInner>
TecInner min(TecInner __x,TecInner __y) {
return __x < __y ? __x : __y;
}
void pushup(int id) {
maxn(id) = max(maxn(lid(id)),maxn(rid(id)));
sumn(id) = sumn(lid(id))+sumn(rid(id));
}
void pushdown(int id,int L,int R) {
lazy(lid(id)) += lazy(id);
lazy(rid(id)) += lazy(id);
int mid = (L+R)>>1;
sumn(lid(id)) += lazy(id)*(mid-L+1);
sumn(rid(id)) += lazy(id)*(R-mid);
maxn(lid(id)) += lazy(id);
maxn(rid(id)) += lazy(id);
tag(lid(id)) += lazy(id);
tag(rid(id)) += lazy(id);
lazy(id) = 0;
}
void tagdown(int id) {
tag(lid(id)) = tag(rid(id)) = id;
}
Tec conduct_max(int id,int L,int R,int l,int r) {
if(R < l||L > r)
return -998244353;
if(tag(id) != -1)
return tag(id);
if(L >= l&&R <= r)
return maxn(id);
pushdown(id);
int mid = (L+R)>>1;
return max(conduct_max(lid(id),L,mid,l,r),
conduct_max(rid(id),mid+1,R,l,r));
}
Tec conduct_sum(int id,int L,int R,int l,int r) {
if(R < l||L > r)
return 0;
if(tag(id) != -1)
return (min(R,r)-max(L,l)+1)*tag(id);
if(L >= l&&R <= r)
return sumn(id);
pushdown(id);
int mid = (L+R)>>1;
return conduct_sum(lid(id),L,mid,l,r)
+conduct_sum(rid(id),mid+1,R,l,r);
}
void con_update(int id,int L,int R,int l,int r,Tec v) {
if(R < l||L > r)
return;
if(L >= r&&R <= r) {
tag(id) = v;
return;
}
pushdown(id);
tagdown(id);
int mid = (L+R)>>1;
con_update(lid(id),L,mid,l,r,v);
con_update(rid(id),mid+1,R,l,r,v);
pushup(id);
}
void con_increase(int id,int L,int R,int l,int r,Tec v) {
if(R < l||L > r)
return;
if(L >= r&&R <= r) {
if(tag(id) != -1)
tag(id) += v;
lazy(id) += v;
return;
}
pushdown(id);
tagdown(id);
int mid = (L+R)>>1;
con_increase(lid(id),L,mid,l,r,v);
con_increase(rid(id),mid+1,R,l,r,v);
pushup(id);
}
void con_con(int id,int L,int R) {
if(L == R) {
maxn(id) = sumn(id) = given[L];
return;
}
int mid = (L+R)>>1;
con_con(lid(id),L,mid);
con_con(rid(id),mid+1,R);
pushup(id);
}
#undef lid
#undef rid
#undef sumn
#undef maxn
#undef tag
public :
Tec get_max(int l,int r) {
return conduct_max(1,1,boarder,l,r);
}
Tec get_sum(int l,int r) {
return conduct_sum(1,1,boarder,l,r);
}
void construct(int size,Tec *in) {
given = in;
boarder = size;
con_con(1,1,boarder);
}
void update(int l,int r,int v) {
con_update(1,1,boarder,l,r,v);
}
void increase(int l,int r,int v) {
con_increase(1,1,boarder,l,r,v);
}
};
SEGMENT_TREE<1000010,int> seg;
signed main() {
}
#include<bits/stdc++.h> using namespace std;
//@cnblogs bikuhiku const int the_size = 262144; int in[the_size], n, m, s, e, v, ans; char judge; struct TREE{ //结构体-树 int left, right; int maxn, sumn, minn; int lid, rid; int lazy; //other information; } tree[the_size]; int cnt; int x = 0, f = 1; char c; inline int g() { //快读; x = 0; f = 1; c = getchar(); for(;(c > '9'||c < '0')&&c != '-';c = getchar()); if(c == '-') { f = -1; c = getchar();} for(;c >= '0'&&c <= '9';c = getchar()) x = (x<<3)+(x<<1)+c-'0'; return x*f; }//快读; inline void discrete(int *a,const int k) { //离散化; int data[the_size]; for(register int i = 1;i <= k;i++) data[i] = a[i]; sort(data+1,data+k+1); int cc = unique(data+1,data+k+1)-data; for(register int i = 1;i <= k;i++) { a[i] = lower_bound(data+1,data+cc,a[i])-data; } return; }//离散化; inline void construct(const int id,const int l,const int r) { //建树; tree[id].left = l; tree[id].right = r; if(l == r) { tree[id].minn = in[l]; tree[id].maxn = in[l]; tree[id].sumn = in[l]; return; }//if is leaf; int mid = (l+r)/2; //the middle point; tree[id].lid = ++cnt; tree[id].rid = ++cnt; construct(tree[id].lid,l,mid); //build the left son_tree; construct(tree[id].rid,mid+1,r); //build the right son_tree; tree[id].minn = min(tree[tree[id].lid].minn,tree[tree[id].rid].minn); //preserve the minn; tree[id].sumn = tree[tree[id].lid].sumn+tree[tree[id].rid].sumn; //preserve the sumn; tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn); //preserve the maxn; return; }//建树; inline void pushdown(const int id) { //下放; tree[tree[id].lid].lazy += tree[id].lazy;//perserve the sign of pushdown(lazy); tree[tree[id].rid].lazy += tree[id].lazy;//perserve the sign of pushdown(lazy); tree[tree[id].lid].sumn += tree[id].lazy*(tree[tree[id].lid].right-tree[tree[id].lid].left+1);//preserve the sumn; tree[tree[id].rid].sumn += tree[id].lazy*(tree[tree[id].rid].right-tree[tree[id].rid].left+1);//preserve the sumn; tree[id].lazy = 0; return; }//下放; inline void pushup(const int id) { //上传; tree[id].sumn = tree[tree[id].lid].sumn+tree[tree[id].rid].sumn; tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn); tree[id].minn = min(tree[tree[id].lid].minn,tree[tree[id].rid].minn); return; }//上传; inline void update(const int id,const int l,const int r,const int val) { //区间修改; if(tree[id].left == l&&tree[id].right == r) { tree[id].lazy += val; tree[id].sumn += val*(tree[id].right-tree[id].left+1); tree[id].maxn += val; tree[id].minn += val; return; }//if is leaf; pushdown(id);//pushdown; int mid = (tree[id].left+tree[id].right)>>1; //find the middle point; if(r <= mid) update(tree[id].lid,l,r,val); //if is left son_tree; else if(l > mid) update(tree[id].rid,l,r,val); //if is right son_tree; else { update(tree[id].lid,l,mid,val); update(tree[id].rid,mid+1,r,val); //zone discover; } pushup(id); return; }//区间修改; inline void modify(const int id,const int sec,const int val) { //修改单点值; if(tree[id].left == tree[id].right) { tree[id].sumn = tree[id].maxn = val; return; }//if is leaf; int mid = (tree[id].left+tree[id].right)>>1; //the middle point; modify(sec <= mid ? tree[id].lid : tree[id].rid,sec,val);// tree[id].sumn = tree[tree[id].lid].sumn + tree[tree[id].rid].sumn; //preserve the sumn; tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn); //preserve the maxn; return; }//修改单点值; inline int query(const int id,const int l,const int r) { //区间求和; if(tree[id].left == l&&tree[id].right == r) { return tree[id].sumn;//if is leaf; } pushdown(id); int mid = (tree[id].left+tree[id].right)>>1;//find the middle point; if(r <= mid) return query(tree[id].lid,l,r); //if is left son_tree; else if(l > mid) return query(tree[id].rid,l,r); //if is right son_tree; else return query(tree[id].lid,l,mid)+query(tree[id].rid,mid+1,r); }//区间求和; inline int majority(const int id,const int l,const int r) { //区间求最大值; if(tree[id].left == l&&tree[id].right == r) { return tree[id].maxn;//if is leaf; } pushdown(id); int mid = (tree[id].left+tree[id].right)>>1;//find the middle point; if(r <= mid) return majority(tree[id].lid,l,r); //if is left son_tree; else if(l > mid) return majority(tree[id].rid,l,r); //if is right son_tree; else return max(majority(tree[id].lid,l,mid),majority(tree[id].rid,mid+1,r)); }//区间求最大值; inline int minority(const int id,const int l,const int r) { //区间求最小值; if(tree[id].left == l&&tree[id].right == r) { return tree[id].minn;//if is leaf; } pushdown(id); int mid = (tree[id].left+tree[id].right)>>1;//find the middle point; if(r <= mid) return minority(tree[id].lid,l,r); //if is left son_tree; else if(l > mid) return minority(tree[id].rid,l,r); //if is right son_tree; else return min(minority(tree[id].lid,l,mid),minority(tree[id].rid,mid+1,r)); }//区间求最小值; inline int point(const int id,const int sec) { //查询单点值 if(tree[id].left == sec&&tree[id].right == sec) { return tree[id].sumn; } pushdown(id); int mid = (tree[id].left+tree[id].right)>>1; if(sec <= mid) return point(tree[id].lid,sec); else return point(tree[id].rid,sec); }//查询单点值; int main() { //主函数; //to do; return 0; }