HDU 4747 Mex
来源:互联网 发布:乐外卖是什么软件 编辑:程序博客网 时间:2024/06/08 02:31
题意:
给出一段数字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;}
0 0
- hdu 4747 Mex
- HDU 4747 Mex
- hdu-4747-Mex
- hdu 4747 Mex
- hdu 4747 Mex
- hdu 4747 Mex
- HDU 4747 Mex
- HDU 4747 Mex
- hdu 4747 Mex
- HDU 4747 Mex
- HDU-4747 Mex
- [HDU 4747 Mex] Mex函数 线段树
- hdu 4747 Mex (线段树)
- hdu 4747 Mex 线段树
- HDU 4747 Mex (线段树)
- HDU 4747 Mex 区间更新
- hdu 4747Mex【线段树】
- HDU 4747 Mex (线段树)
- 项目管控模式的核心
- HUDJ 2044 一只小蜜蜂... 递推
- Spring mvc中@Requestmapping再探
- JDBC操作数据库日期
- Light OJ 1094 - Farthest Nodes in a Tree
- HDU 4747 Mex
- poj 3041
- Apache POI 读取大于10位数字会变科学数字的解决方案
- chap11 stack
- ubuntu 12.04创建多用户及开启telnet远程登录
- IAR包含文件的路径定义
- linux下vim编辑器使用
- hdu 1505
- VS关于“调试并编辑”功能的说明