当前位置:网站首页>HDU 4747 Mex「建议收藏」
HDU 4747 Mex「建议收藏」
2022-07-07 21:51:00 【全栈程序员站长】
大家好,又见面了,我是全栈君。
题意:
给出一段数字a 定义mex(l,r)表示a[l]…a[r]中最小的不连续的数字 求出全部mex(l,r)的和
思路:
首先能够想到由l開始到n的全部数字的mex值必定是递增的 那么就能够求出以1開始到n的全部数字的mex 从前到后扫一遍就可以 这时能够求出[1,r]全部区间的mex和 利用线段树就可以
接着考虑怎样求[2,r]、[3,r]…. 由[1,r]到[2,r]的转变无非是去掉第一个数字 那么去掉一个数字的影响是什么呢?
比方去掉一个2 那他最多影响到下一个2出现的地方 并且 他仅仅是把mex>2的地方改成了2 即从2处截断 又由于之前所说的递增关系 所以影响的区间也一定是连续的!
那么我们就能够每次删掉一个数字 利用线段树找出他影响的区间 并把这个区间覆盖为那个删掉的数字
最后每次求和就是答案
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef __int64 ll;
#define N 201000
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
struct node
{
int l,r,val,lazy;
ll sum;
}tree[N*4];
int a[N],mex[N],next[N];
int n,l,r;
map<int,int> mp;
ll ans;
void up(int i)
{
tree[i].val=max(tree[L(i)].val,tree[R(i)].val);
tree[i].sum=tree[L(i)].sum+tree[R(i)].sum;
}
void down(int i)
{
if(tree[i].lazy!=-1)
{
tree[L(i)].lazy=tree[i].lazy;
tree[L(i)].val=tree[i].lazy;
tree[L(i)].sum=(tree[L(i)].r-tree[L(i)].l+1)*tree[i].lazy;
tree[R(i)].lazy=tree[i].lazy;
tree[R(i)].val=tree[i].lazy;
tree[R(i)].sum=(tree[R(i)].r-tree[R(i)].l+1)*tree[i].lazy;
tree[i].lazy=-1;
}
}
void init(int l,int r,int i)
{
tree[i].l=l; tree[i].r=r; tree[i].lazy=-1;
if(l==r)
{
tree[i].val=mex[l];
tree[i].sum=mex[l];
return ;
}
int mid=(l+r)>>1;
init(l,mid,L(i));
init(mid+1,r,R(i));
up(i);
}
void update(int l,int r,int i,int k)
{
if(l==tree[i].l&&r==tree[i].r)
{
tree[i].sum=(tree[i].r-tree[i].l+1)*k;
tree[i].val=k;
tree[i].lazy=k;
return ;
}
down(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid) update(l,r,L(i),k);
else if(l>mid) update(l,r,R(i),k);
else
{
update(l,mid,L(i),k);
update(mid+1,r,R(i),k);
}
up(i);
}
void query(int i,int k)
{
if(tree[i].l==tree[i].r)
{
if(tree[i].val>k) l=tree[i].l;
else l=n+1;
return ;
}
down(i);
if(tree[L(i)].val>k) query(L(i),k);
else query(R(i),k);
up(i);
}
int main()
{
int i,j;
while(~scanf("%d",&n))
{
if(!n) break;
mp.clear(); // get mex
j=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
mp[a[i]]=1;
while(mp[j]) j++;
mex[i]=j;
}
mp.clear(); // get next
for(i=1;i<=n;i++) mp[a[i]]=n+1;
for(i=n;i>=1;i--)
{
next[i]=mp[a[i]];
mp[a[i]]=i;
}
//for(i=1;i<=n;i++) printf("%d %d\n",mex[i],next[i]);
init(1,n,1);
for(i=1,ans=0;i<=n;i++)
{
ans+=tree[1].sum;
query(1,a[i]);
r=next[i];
//printf("%d %d\n",l,r);
if(l<r)
{
update(l,r-1,1,a[i]);
}
update(i,i,1,0);
}
printf("%I64d\n",ans);
}
return 0;
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116215.html原文链接:https://javaforall.cn
边栏推荐
- Clean C disk
- Vulnerability recurrence ----- 49. Apache airflow authentication bypass (cve-2020-17526)
- Mysql索引优化实战一
- leetcode-520. 检测大写字母-js
- The text editor of markdown class should add colors to fonts (including typora, CSDN, etc.)
- Unity3D学习笔记5——创建子Mesh
- LeeCode -- 6. Zigzag transformation
- LeeCode -- 6. Z 字形变换
- Inftnews | the wide application of NFT technology and its existing problems
- 网络安全-beef
猜你喜欢
Talk about the design and implementation logic of payment process
云原生正在吞噬一切,开发者该如何应对?
Wechat forum exchange applet system graduation design completion (7) Interim inspection report
Unity3D学习笔记5——创建子Mesh
js 获取对象的key和value
Matlab 信号处理【问答随笔·2】
leetcode-520. Detect capital letters -js
ROS2专题(03):ROS1和ROS2的区别【02】
在软件工程领域,搞科研的这十年!
Wechat forum exchange applet system graduation design (5) assignment
随机推荐
微信论坛交流小程序系统毕业设计毕设(8)毕业设计论文模板
Matlab 信号处理【问答随笔·2】
微信论坛交流小程序系统毕业设计毕设(2)小程序功能
云原生正在吞噬一切,开发者该如何应对?
GEE(四):计算两个变量(影像)之间的相关性并绘制散点图
Inftnews | web5 vs Web3: the future is a process, not a destination
Adrnoid开发系列(二十五):使用AlertDialog创建各种类型的对话框
JMeter-接口自动化测试读取用例,执行并结果回写
ArcGIS: field assignment_ The attribute table field calculator assigns values to fields based on conditions
RE1 attack and defense world reverse
VS扩展工具笔记
LDO稳压芯片-内部框图及选型参数
php 使用阿里云存储
微信论坛交流小程序系统毕业设计毕设(6)开题答辩PPT
Grid
Brush question 6
FreeLink开源呼叫中心设计思想
树后台数据存储(採用webmethod)[通俗易懂]
Exploratory data analysis of heartbeat signal
JMeter interface automated test read case, execute and write back result