首页 > 其他分享 >线段树分治结构

线段树分治结构

时间:2023-07-17 17:25:32浏览次数:39  
标签:rt node int 线段 分治 tree line op 结构

目录

线段树分治结构

基本知识:

应用点: 当有些东西一会出现,一会又不出现时,可以使用线段树分治
方式: 维护某一个东西出现的时间段,并在线段树上打上标记,并dfs
遇到标记后,就相当于加入了这个物品。当dfs到叶子节点后,就可以得到叶子节点所代表的时间的性质
dfs返回时,若经过遇到标记的地方,需要撤回这个标记,相当于这个物品不再在答案统计内
正因如此,若是要用某个结构来维护性质,要求能够撤回
这些常见的结构有:线性运算/并查集(例题1)/dp方程式(例题2)

例题1: 模板(基础题)

题目链接:https://www.luogu.com.cn/problem/P5787
AC记录:https://www.luogu.com.cn/record/116043014
思想: 并查集维护同色关系,可以拆点或带权并查集,利用栈来维护撤回操作
代码:


#include<bits/stdc++.h>
using namespace std;
int n,m,k;
struct node{
	int l,r,x,y;
}line[200005];
struct nod{
	int ll;
	int rr;
}tree[800045];
int d[200005];
stack<pair<int,bool>>s;
vector<pair<int,int>>flag[800045];
void build(int rt,int l,int r){
	tree[rt].ll=l;
	tree[rt].rr=r;
	if(l==r){
		return;
	}
	int mid=(l+r)/2;
	build(rt*2,l,mid);
	build(rt*2+1,mid+1,r);
}
void updata(int rt,int cl,int cr,int flag1,int flag2){
	int le=tree[rt].ll;
	int ri=tree[rt].rr;
	if(le>cr||ri<cl){
		return;
	}
	if(le>=cl&&ri<=cr){
		flag[rt].push_back(make_pair(flag1,flag2));
		return;
	}
	updata(rt*2,cl,cr,flag1,flag2);
	updata(rt*2+1,cl,cr,flag1,flag2);
}
//-----------------------------------------打标记线段树 
int fa[400005];
int fid(int x){
	if(x==fa[x]){
		return x;
	}
	else{
		return fid(fa[x]);
	}
}
void he(int x, int y){
	x=fid(x);
	y=fid(y);
	if(x==y){
		return;	
	} 
	if(d[x]>d[y]) swap(x, y);
	s.push(make_pair(x,d[x]==d[y]));
	fa[x]=y;
	if(d[x]==d[y]){
		d[y]++;
	}
}

void dfs(int rt,int right){
	int l=tree[rt].ll;
	int r=tree[rt].rr;
	int o=s.size();
	for(int i=0;i<flag[rt].size();i++){
		int a=flag[rt][i].first;
		int b=flag[rt][i].second;
		if(fid(a)==fid(b)){
			for(int j=l;j<=r;j++){
				cout<<"No"<<endl;
				
			}
			right=0;
			break;
		}
		else{
			he(a,b+n);
			he(b,a+n);
		}
		
	}//标记使用
	if (right) {
		if (l==r){
			cout<<"Yes"<<endl;
		}
		else{
			dfs(rt*2,right); 
			dfs(rt*2+1,right);
		} 
	}
	while (s.size() > o){
		d[fa[s.top().first]]-=s.top().second;
		fa[s.top().first]=s.top().first;
		s.pop();
	} 
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n >> m >> k;
	build(1,0,k-1);
	for(int i=1;i<=m;i++){
		cin >> line[i].x>>line[i].y>>line[i].l>>line[i].r;
		line[i].r--;
		updata(1,line[i].l,line[i].r,line[i].x,line[i].y);
	}
	for(int i=1;i<=2*n;i++){
		fa[i]=i;
		d[i]=1;
	}
	dfs(1,1);
	
	
}

例题2: dp(背包)(会了就掌握题)

题目链接:http://222.180.160.110:1024/problem/5503
也可以去:https://loj.ac/p/6515
思想: 物品我一个个加入,同理我也可以一个个撤回,其实还是枚举了物品的,不过是有规律的罢了,利用cnt来记录物品进入先后关系(从而好撤回)
代码:有点难写啊

#include<bits/stdc++.h>
using namespace std;
int t,m,mod;
const int M=50005;
int tmm[M];
int L[M],R[M],ans[M];
struct node{
	int tim;
	int w;
	int v;
};
//----------------------pack
int dp[M][505]; 
int cnt=0;
void clear(){
	for(int i=0;i<M;i++){
		for(int j=0;j<500;j++){
			dp[i][j]=-0x3f3f3f3f;
		}
	}
	dp[0][0]=0;
}
void insert(pair<int,int>now){
	int x=now.first%mod;
	int y=now.second;
	cnt++;
	for(int i=0;i<mod;i++){
		dp[cnt][i]=dp[cnt-1][i];
	}
	for(int i=0;i<mod;i++){
		if(x<=i){
			dp[cnt][i]=max(dp[cnt][i],dp[cnt-1][i-x]+y);
		}
		else{
			dp[cnt][i]=max(dp[cnt][i],dp[cnt-1][i+mod-x]+y);
		}
	}
}
void recall(){
	for(int i=0;i<500;i++){
		dp[cnt][i]=-0x3f3f3f3f;
	}
	cnt--;
}
int query(int l,int r){
	int ret=-1;
	for(int i=l;i<=r;i++){
		ret=max(ret,dp[cnt][i]);
	}
	return ret;
}

//---------------------tree
struct nod{
	int ll;
	int rr;
}tree[4*M];
vector<pair<int,int>>flag[4*M];
void build(int rt,int l,int r){
	tree[rt].ll=l;
	tree[rt].rr=r;
	if(l==r){
		return;
	}
	int mid=(l+r)/2;
	build(rt*2,l,mid);
	build(rt*2+1,mid+1,r);
}
void updata(int rt,int cl,int cr,int weight,int value){
	int le=tree[rt].ll;
	int ri=tree[rt].rr;
	if(le>cr||ri<cl){
		return;
	}
	if(le>=cl&&ri<=cr){
		flag[rt].push_back(make_pair(weight,value));
		return;
	}
	updata(rt*2,cl,cr,weight,value);
	updata(rt*2+1,cl,cr,weight,value);
}
void solve(int rt){
	int l=tree[rt].ll;
	int r=tree[rt].rr;
	int sz=flag[rt].size();
	for(int i=0;i<sz;i++){
		insert(flag[rt][i]);
	}
	if(l^r){
		solve(rt*2);
		solve(rt*2+1);
		
	}
	else if(L[l]^-1){
		ans[l]=query(L[l],R[r]);
	}
	
	for(int i=0;i<sz;i++){
		recall();
	}
}
//---------------------------tree
int main(){
		ios::sync_with_stdio(false);
		cin >> t;
		cin >> m >> mod;
		clear();
		memset(L,-1,sizeof(L));
		build(1,1,m); 
		deque<node>q;
		for(int i=1;i<=m;i++){
			string op;
			cin >> op;
			int w,v;
			if(op[0]=='I'&&op[1]=='F'){
				cin >> w >> v;//前面放 
				node Q=(node){i,w,v};
				q.push_front(Q);
			}
			else if(op[0]=='I'&&op[1]=='G'){
				cin >> w >> v;//后面放 
				node Q=(node){i,w,v};
				q.push_back(Q);
			}
			else if(op[0]=='D'&&op[1]=='F'){//删除前面 
				node Q=q.front();
				q.pop_front();
				updata(1,Q.tim,i-1,Q.w,Q.v);
			}
			else if(op[0]=='D'&&op[1]=='G'){//删除后面 
				node Q=q.back();
				q.pop_back();
				updata(1,Q.tim,i-1,Q.w,Q.v);//区间标记 
			}
			else if(op[0]=='Q'&&op[1]=='U'){
				int l,r;
				cin >> l >> r;//w和mod在l-r区间内最强武力值 
				L[i]=l;
				R[i]=r;
			}
		}
		while(q.size()){
			node Q=q.front();
			q.pop_front();
			updata(1,Q.tim,m,Q.w,Q.v);//永远不会消失的要注意添加 
		}
		solve(1);
		for(int i=1;i<=m;i++){
			if(L[i]^-1){
				cout<<ans[i]<<endl;
			}
		}
	
}

标签:rt,node,int,线段,分治,tree,line,op,结构
From: https://www.cnblogs.com/linghusama/p/17560657.html

相关文章

  • 哈希数据结构
    参考链接:https://blog.csdn.net/CRMEB/article/details/1208206821.哈希表哈希表,即散列表(Hashtable),是根据keyvalue而直接进行访问的数据结构。也就是说,它通过把keyvalue映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。......
  • 数据结构
    数据结构中的基本概念  数据:任何能够输入到计算机中,能被程序处理的描述客观事物的符号  数据项:有独立含义的最小单位,也叫做数据域、域  数据元素:组成数据的、有一定意义的基本单位,也叫作节点、结点、顶点(一个数据元素是由若干项数据项组成)  数据结构:相互之间......
  • 纯css 四边形的角样式(只有两个角是三角,其他两个是线段)
    效果如图:核心:使用伪类代码如下:<divclass="box-style"></div>.box-style{position:relative;//纯css只有四个角有边框的样式box-shadow:0px0px12px1px#003ba26binset;background:linear-gradient(toleft,#1f5fd3,#1f5fd3)lefttopno-repeat,......
  • 7.17 数据结构
    线段树小白逛公园动态维护最大子段和,没啥好说的文文的摄影布置考虑清楚标记分讨合并算术天才⑨与等差数列维护区间最大最小,如果是等差数列,有了端点就可以知道整个序列了,再维护哈希值对比就可以了,突然发现我之前这个解法是乱搞,只有充分性没有必要性,只是题目没有卡正解:维护......
  • 数据结构小记
    线段树区间查询线段树可以维护具有结合律的信息。区间修改区间查询加上修改后应当满足的前提是我们可以维护一个封闭的集合\(\mathcal{S}\),使得任一操作\(o\in\mathcal{S}\),且\(\mathcal{S}\)对于复合封闭,即对任意\(u,v\in\mathcal{S}\),有\(u\circv\in\mathcal{S}\)......
  • python学习_循环结构(while循环和for循环)
    一、什么叫循环结构?反复做同一件事情的情况,就要循环python中的循环结构主要有两种:1)while2)for-in 二、while循环只要条件成立,其包含的某条语句或某个语句块就会一直被执行,while循环与if语句的区别就是if语句是判断一次,条件为True就执行一次执行体,while循环是判断N+1次,条件......
  • 29结构化设计(高内聚)
    内聚是一个模块内各个元素的联系程度内聚程度从高到低:处理元素相关:功能内聚。完成一个单一功能,各个部分协同工作,缺一不可顺序内聚:处理元素相关,必须按顺序执行通信内聚:处理元素同在一个数据结构过程内聚:处理元素按一定次序执行任务相关:时间内聚:任务按一定时间间隔执行逻......
  • 28结构化设计
    结构化设计包括:概要设计(外部),设计各个模块子系统详细设计(内部),具体的处理方法 结构化设计原则:模块独立性原则(高内聚,低耦合)保持模块大小适中多扇入,少扇出(扇入指调用,扇出指耦合度)深度和跨度不宜过高......
  • 二. 基础数据结构
    二.基础数据结构0.引JSON是一个有着特殊结构的数据,为了解析JSON,需要使用编程语言将JSON的数据格式进行抽象,有助于更好地,快捷地实现JSON数据的解析.为了使解析JSON结构的性能更好,选用C语言实现JSON的数据结构的抽象,以及底层的结构的解析功能实现.1.JSON基础数......
  • JVM专栏-类文件结构
    JVM的“无关性”谈论JVM的无关性,主要有以下两个:平台无关性:任何操作系统都能运行Java代码语言无关性:JVM能运行除Java以外的其他代码Java源代码首先需要使用Javac编译器编译成.class文件,然后由JVM执行.class文件,从而程序开始运行。JVM只认识.class文件,......