当前位置:网站首页>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
边栏推荐
- Unity3D学习笔记6——GPU实例化(1)
- Add data analysis tools in Excel
- Coreseek: the second step is index building and testing
- The text editor of markdown class should add colors to fonts (including typora, CSDN, etc.)
- UE4_UE5蓝图command节点的使用(开启关闭屏幕响应-log-发布全屏显示)
- Oracle-数据库的备份与恢复
- ./ setup. Insufficient sh permission
- Installing vmtools is gray
- 违法行为分析1
- 14、 Two methods of database export and import
猜你喜欢
微信论坛交流小程序系统毕业设计毕设(2)小程序功能
Wechat forum exchange applet system graduation design (3) background function
Inftnews | the wide application of NFT technology and its existing problems
PCI-Express接口的PCB布线规则
UE4_UE5蓝图command节点的使用(开启关闭屏幕响应-log-发布全屏显示)
USB(十五)2022-04-14
14、 Two methods of database export and import
Mysql索引优化实战一
LeeCode -- 6. Z 字形变换
Gee (IV): calculate the correlation between two variables (images) and draw a scatter diagram
随机推荐
二叉树(Binary Tree)
turbo intruder常用脚本
ROS2专题(03):ROS1和ROS2的区别【01】
Experience sharing of system architecture designers in preparing for the exam: the direction of paper writing
Network security - Eternal Blue
Brush question 5
微信论坛交流小程序系统毕业设计毕设(4)开题报告
V20变频器手自动切换(就地远程切换)的具体方法示例
七月第一周
Network security - joint query injection
Two kinds of curves in embedded audio development
What are the similarities and differences between smart communities and smart cities
648. 单词替换
智慧社區和智慧城市之間有什麼异同
云原生数据仓库AnalyticDB MySQL版用户手册
UE4_UE5全景相机
ArcGIS:矢量要素相同字段属性融合的两种方法
Count the top 10 films at the box office and save them in another file
Byte hexadecimal binary understanding
Ros2 topic (03): the difference between ros1 and ros2 [01]