c语言海报,C语言 竞选海报

本文详细介绍了使用C/C++实现线段树数据结构来处理动态海报覆盖的问题。通过线段树,可以高效地插入、更新和查询墙面上海报的数量。线段树的节点包含了左边界、右边界、标志域、海报编号等信息,并利用标志域优化了完全覆盖的情况,减少了不必要的更新操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C/C++ code#include

using namespace std;

#define LEN 20000

#define NO_POSTER -2 //无海报

#define MIX_POSTER -1 //混合(间断)海报

#define NO_FLAG 0

//线段树的静态表示,左边界,右边界,标志域,结点对应海报编号,海报能否看见的标记数组,结点数量,最终能看见的海报数量

int left_bound[LEN],right_bound[LEN],flag[LEN],poster[LEN],ref[LEN],node_num,count_poster;

//clear(int index),更新poster[index],flag[index],flag[left_child[index]],flag[right_child[index]]

void clear(int index)

{

poster[index]=flag[index];

flag[2*index]=flag[index];

flag[2*index+1]=flag[index];

flag[index]=NO_FLAG;

}

//创建线段树

void construct(int left,int right,int num=1)

{

++node_num;

left_bound[num]=left;

right_bound[num]=right;

poster[num]=NO_POSTER;

if(left+1

{

int mid=(left+right)/2;

construct(left,mid,2*num);

construct(mid,right,2*num+1);

}

}

//贴海报

void insert(int index,int left,int right,int num)

{

if(flag[index]!=NO_FLAG) //如果有标志域,说明被完全覆盖过,所以更新自己的海报信息与孩子的标志域******PS:标志域的作用就是当前结点与之下子结点信息一致时,免去一次性全部更新的浪费

//先用标志域存储起来,下次需要用时临时更新需要的结点获得信息..看下一条注释!

{

clear(index);

}

if(left==left_bound[index]&&right_bound[index]==right)//例如: 如果某结点完全覆盖,那么它的子结点与该结点继承同一海报,所以这时候用标志域比用poster[]记录要有效得多!看下一条注释!

{

flag[index]=num;

return;

}

else//如果没有完全覆盖,那么就不能标志当前结点的flag,因为子结点与该结点没有相同的特征,子结点只是零散的覆盖该结点,所以这时只要修改poster[index]为混合标记就可以了.

{

poster[index]=MIX_POSTER;

int mid=(left_bound[index]+right_bound[index])/2;

if(left

{

insert(2*index,left,right,num);

}

if(leftmid)

{

insert(2*index,left,mid,num);

insert(2*index+1,mid,right,num);

}

if(left>=mid&&right>mid)

{

insert(2*index+1,left,right,num);

}

}

}

//数海报数量,这里完全依赖于poster[]的记录来数海报数量,所以必须根据flag刷新被完全覆盖结点的海报编号. 判断条件依赖于: poster[] 中有编号,混合海报,没有覆盖海报,一共三个情况。

void count(int index)

{

if(flag[index]!=NO_FLAG)

{

clear(index);

}

if(poster[index]!=NO_POSTER)

{

if(poster[index]!=MIX_POSTER)

{

if(ref[poster[index]]==0)

{

ref[poster[index]]=1;

++count_poster;

}

}

else

{

count(2*index);

count(2*index+1);

}

}

}

int main()

{

node_num=0;

count_poster=0;

memset(ref,0,sizeof(ref));

int num;//海报数量

int left,right;//海报覆盖范围

cin>>left>>right>>num;//输入墙的范围

construct(left,right);//构造线段树

for(int cnt=1;cnt<=num;++cnt)

{

cin>>left>>right;

insert(1,left,right,cnt);

}

count(1);

cout<

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值