IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构题目总结 -> 正文阅读

[数据结构与算法]数据结构题目总结

1.关押罪犯

思路:将每个罪犯分成两个点,一个是他本身,另一个是表示不与他一个监狱的点,从高到低排序每对罪犯的怨气值,每次先查询两个罪犯是否在一个牢房,若在直接输出,反之将两个人相互与对方表示不再一个牢房的点连边

2.hotel

思路:建立线段树,每个节点保存本段最长,靠左最长,靠右最长,每次修改时记录懒标记区间修改,然后用儿子节点的值更新父亲节点;查询时先选择左儿子,再选择区间跨越左右两个节点,最后选择右儿子

3.picture

思路:扫描线,因为每次修改都会导致边长的变化,所以答案要加上边长变化的值,扫描线横着扫一次,竖着扫一次后相加得出答案

void build(int id,int l,int r){
	tr[id].l=l;
	tr[id].r=r;
	tr[id].ans=tr[id].cs=0;
	if(l+1==r) return ;//扫描线的线段树存放的是线段,所以长度不能相等
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid,r);
}
void insert(int id,int x,int y,int w){
	int l=tr[id].l,r=tr[id].r;
	if(l>=x&&r<=y){
		tr[id].cs+=w;
		if(tr[id].cs) tr[id].ans=r-l;//只有线段没有被覆盖才会用儿子节点更新
		else tr[id].ans=(l==r?0:tr[id<<1].ans+tr[id<<1|1].ans);
		return ;
	}
	int mid=(l+r)>>1;
	if(x<tr[id<<1].r) insert(id<<1,x,y,w);
	if(y>tr[id<<1|1].l) insert(id<<1|1,x,y,w);
	tr[id].ans=(tr[id].cs?tr[id].ans:tr[id<<1].ans+tr[id<<1|1].ans);
}

4.作诗

思路:分块,并且记录以i结尾的块数字出现次数的前缀和,并且统计l~r块中答案,每次询问时候答案初始为ans[id[l]+1][id[r]-1],在答案的基础上枚举不成整块的数的出现次数修改答案

struct fk{
	int sum[350][100010],n,id[100100],l[350],r[350],len,w[1000010],ans[350][350],cnt[100010];
	void init(){
		for(int i=1;i<=n;i++){
			id[i]=(i-1)/len+1;
		}
		for(int i=1;i<=n/len;i++){
			l[i]=r[i-1]+1;
			r[i]=i*len;
		}
		if(n%len){
			l[n/len+1]=r[n/len]+1;
			r[n/len+1]=n;
		}
		for(int i=1;i<=n;i++){//记录前缀和
			if(id[i]!=id[i-1]){
				for(int j=1;j<=n;j++){
					sum[id[i]][j]=sum[id[i]-1][j];
				} 
			}
			sum[id[i]][w[i]]++;	
		}
		for(int i=1;i<=ceil((double)n/len);i++){//统计答案,每次答案都从ans[i][j-1]上更新
			for(int j=i;j<=ceil((double)n/len);j++){
				ans[i][j]=ans[i][j-1];
				for(int k=l[j];k<=r[j];k++){
					int p=w[k];
					cnt[p]++;
					int gs=sum[j-1][p]-sum[i-1][p];
					if((gs+cnt[p])%2==0&&(gs+cnt[p])) ans[i][j]++;//成偶数++;
					else if((gs+cnt[p])>1) ans[i][j]--;//反之从以前加的上减去
				}
				for(int k=l[j];k<=r[j];k++){
					int p=w[k];
					cnt[p]--;
				}
			}
		}
	}
	int query(int le,int ri){
		int num=0;
		if(id[le]==id[ri]){
			for(int i=le;i<=ri;i++){
				int p=w[i];
				cnt[p]++;
				if(cnt[p]%2==0) num++;
				else if(cnt[p]>1&&cnt[p]%2==1) num--;
			}
			for(int i=le;i<=ri;i++) cnt[w[i]]--;
			return num;
		}
		num=ans[id[le]+1][id[ri]-1];
		//cout<<"*"<<num<<endl;
		for(int i=le;i<=r[id[le]];i++){
			int p=w[i];
			cnt[p]++;
			int gs=sum[id[ri]-1][p]-sum[id[le]][p];
			if((gs+cnt[p])%2==0) num++;
			else if((gs+cnt[p])>1) num--;
		}
		for(int i=l[id[ri]];i<=ri;i++){
			int p=w[i];
			cnt[p]++;
			int gs=sum[id[ri]-1][p]-sum[id[le]][p];
			if((gs+cnt[p])%2==0) num++;
			else if((gs+cnt[p])>1) num--;
		}
		for(int i=le;i<=r[id[le]];i++) cnt[w[i]]--;
		for(int i=l[id[ri]];i<=ri;i++) cnt[w[i]]--;
		return num;
	}
};

5.race

思路:先用点分治找到所有权值和等于k的链的左右端点,然后再在树上跑lca查询到两个节点的距离更新答案

void get_ans(int x){/点分治
	d[x]=0;
	id[x]=x;
	cnt=0;
	num[++cnt]=x;
	for(int i=0;i<tu[x].size();i++){
		int p=tu[x][i].p;
		int w=tu[x][i].w;
		if(vis[p]) continue;
		get_d(p,x,w,p);
	}
	sort(num+1,num+cnt+1,cmp);
	int l=1,r=cnt;
	while(l<r){
		if(d[num[l]]+d[num[r]]>w){
			r--;
			continue;
		}
		if(d[num[l]]+d[num[r]]<w){
			l++;
			continue;
		}
		
		if(id[num[l]]==id[num[r]]){
		    l++;
			continue;
		}
		if(!mp[num[l]][num[r]]){//满足相等且不在一个子树的节点
			mp[num[l]][num[r]]=true;
			ans_cnt++;
			ans[ans_cnt].from=num[l];
			ans[ans_cnt].to=num[r];//记录下节点所在链的左右端点
			 l++;
		}else{

			 l++;
		}
	}
}

6.营业额统计

用treap维护数据并且查询每个数的前驱和后继,要求绝对值最小,就取最后一个比他大的和第一个比他小的分别与其做差更新答案

struct treap{
	int rnd[50010],sz[50001],w[50001],gs[50010],l[50001],r[50001],size,root,ans;
	void pushup(int x){
		sz[x]=sz[l[x]]+sz[r[x]]+gs[x];
	}
	void lr(int &k){
		int t=r[k];
		r[k]=l[t];
		l[t]=k;
		sz[t]=sz[k];
		pushup(k);
		k=t;
	}
	void rr(int &k){
		int t=l[k];
		l[k]=r[t];
		r[t]=k;
		sz[t]=sz[k];
		pushup(k);
		k=t;
	}
	void insert(int &k,int x){
		if(!k){
			size++;
			k=size;
			w[k]=x;
			sz[k]=1;
			rnd[k]=rand();
			gs[k]=1;
			return ;
		}
		sz[k]++;
		if(w[k]==x){
			gs[k]++;
		}else{
			if(x>w[k]){
				insert(r[k],x);
				if(rnd[k]<rnd[r[k]]) lr(k);
			}else{
				insert(l[k],x);
				if(rnd[k]<rnd[l[k]]) rr(k);
			}
		}
	}
	void get_pre(int k,int x){//treap查前驱
		if(!k) return ;
		if(w[k]==x){
			ans=k;
			return ;
		}
		if(w[k]<x){
			ans=k;//比他小就更新答案
			get_pre(r[k],x);
		}else{
			get_pre(l[k],x);
		}
	}
	void get_sub(int k,int x){//treap查后继
		if(!k) return ;
		if(w[k]==x){
			ans=k;
			return ;
		}
		if(w[k]>x){
			ans=k;
			get_sub(l[k],x);
		}else{
			get_sub(r[k],x);
		}
	}
};

?7.mokia

思路:cdq分治,将查询区间转换为二维前缀和(a[l1][r1]~a[l2][r2]=sum[l2][r2]-sum[l1-1][r2]-sum[l2][r1-1]+sum[l1-1][l2-1]),然后用cdq分治(时间,x,y)三维偏序解决

void cdq(int l,int r){
	if(l==r) return ;
	int mid=(l+r)>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	for(int i=l;i<=mid;i++) p1[i]=p[i];
	for(int i=mid+1;i<=r;i++) p2[i]=p[i];
	sort(p1+l,p1+mid+1,cmp);
	sort(p2+mid+1,p2+r+1,cmp);
	int x=l;
	for(int i=mid+1;i<=r;i++){
		if(p2[i].op==1) continue;
		while(p1[x].x<=p2[i].x&&x<=mid){
			if(p1[x].op==2){
				x++;
				continue;
			}
			ty.insert(p1[x].y,p1[x].w);
			x++;
		} 
		ans[p2[i].id]=ans[p2[i].id]+p2[i].w*ty.query(p2[i].y);
	}
	for(int i=l;i<x;i++){
		if(p1[i].op==1){
			ty.erase(p1[i].y,p1[i].w);
		}
	}
}

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 12:07:09  更:2021-08-27 12:08:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:42:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码