【模板】线段树(&离散化)

适用于区间染色及查询颜色段数
#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; }

  

@bikuhiku

posted @ 2022-02-20 08:05  bikuhiku  阅读(24)  评论(0编辑  收藏  举报