hdu-4747-Mex-线段树区域更新
来源:互联网 发布:公务员可以开淘宝店吗 编辑:程序博客网 时间:2024/05/21 06:42
部分题解摘抄cxlove,传送门:http://blog.csdn.net/acm_cxlove/article/details/11749383
题目:给出一个序列,mex{}表示集合中没有出现的最小的自然数。然后 求sigma(mex (i , j)).
做法:考虑左端点固定时的所有区间的mex值,这个序列是一个非递减了。。。首先要明白。
初始就是求出mex[i]表示 mex(1 , i),对于每一个左端点,就是一个区间求和。
现在需要考虑的是左端点的改变对于序列的影响。。。
即左端点从i -> i + 1,mex[j]的改变。。。。即删去ai对于序列的影响。
如果 a[j] = a[i] 且 j > i ,不存在a[k] = a[i] j > k > i。即a[i]下一次出现的位置 。
根据mex的定义,我们知道 mex[k]不会改变, k >= j。因为删掉的ai还是存在于序列当中,所以不受影响。
之后需要考虑的是i +1 到 j - 1这段区间的mex值。。。删去了ai之后,使得原先mex值大于ai的,都会更新成ai。
很好理解。。。因为是没有出现的最小的,ai更小。。。
之前说过这是一个非递减的序列,所以原先mex值大于ai的也是一段连续的区间,所以我们可以找到最靠左的位置 r,使得mex[r] > a[i]。那么r 到 j - 1这段区间的mex值便 会更新为a[i]。
所以全部搞定。。。用线段树维护一下mex序列,区间更新,区间求和,然后一个查找就可以了。。。
以上是cxlove的博客的题解。
说白了,就是寻找一段区域,然后区域更新这段区域。
然后sum[1]代表全部区域的和。
#include<stdio.h>#include<iostream>#include<stdlib.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;#define maxn 220000#define lmin 1#define rmax n#define lson l,(l+r)/2,rt<<1#define rson (l+r)/2+1,r,rt<<1|1#define root lmin,rmax,1#define now l,r,rt#define INF 99999999#define LL __int64vector<LL>vec[maxn];LL fail[maxn];LL mex[maxn];LL vis[maxn];LL a[maxn];LL val[maxn*4];LL sum[maxn*4];LL maxx[maxn*4];LL lazy[maxn*4];void push_up(int l,int r,int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);}void push_down(int l,int r,int rt){ if(lazy[rt]!=-1) { int mid=(l+r)/2; lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; maxx[rt<<1]=maxx[rt<<1|1]=lazy[rt]; sum[rt<<1]=lazy[rt]*(mid-l+1); sum[rt<<1|1]=lazy[rt]*(r-mid); lazy[rt]=-1; }}void creat(int l,int r,int rt){ val[rt]=sum[rt]=maxx[rt]=0; lazy[rt]=-1; if(l!=r) { creat(lson); creat(rson); push_up(now); return; } val[rt]=sum[rt]=maxx[rt]=mex[l];}void update(int ll,int rr,LL x,int l,int r,int rt){ if(ll>r||rr<l)return; if(ll<=l&&rr>=r) { lazy[rt]=x; sum[rt]=(r-l+1)*x; maxx[rt]=x; return; } push_down(now); update(ll,rr,x,lson); update(ll,rr,x,rson); push_up(now);}int querymax(LL x,int l,int r,int rt){ if(maxx[rt]<x)return INF; if(l==r)return l; push_down(now); int ans=INF; ans=querymax(x,lson); if(ans==INF)ans=querymax(x,rson); return ans;}int main(){ int T,n; while(~scanf("%d",&n)&&n) { LL ans=0; for(int i=0; i<=n+1; i++) { fail[i]=0; vec[i].clear(); } for(int i=1; i<=n; i++) { scanf("%I64d",&a[i]); if(a[i]>n)a[i]=n+1; vec[a[i]].push_back(i); } memset(vis,0,sizeof(vis)); int l=0; for(int i=1; i<=n; i++) { vis[a[i]]=1; for(l; vis[l]; l++); mex[i]=l; ans+=mex[i]; } creat(root); // cout<<ans<<endl; int index; for(int i=1; i<n; i++) { fail[a[i]]++; if(fail[a[i]]<vec[a[i]].size())index=vec[a[i]][fail[a[i]]]; else index=n+1; int l=querymax(a[i],root); if(l<index) { update(l,index-1,a[i],root); } ans+=sum[1]; } cout<<ans<<endl; } return 0;}
- hdu-4747-Mex-线段树区域更新
- [HDU 4747 Mex] Mex函数 线段树
- hdu 4747 Mex(线段树区间更新+二分)
- hdu 4747 Mex (线段树)
- hdu 4747 Mex 线段树
- HDU 4747 Mex (线段树)
- hdu 4747Mex【线段树】
- HDU 4747 Mex (线段树)
- hdu - 4747 - Mex(二分+线段树)
- hdu 4747 Mex(线段树)
- hdu 4747 Mex(线段树)
- HDU 4747 Mex (线段树)
- HDU 4747 Mex (线段树)
- HDU 1698(线段树 区域更新,区域求值)
- HDU 4747 Mex 区间更新
- HDU 4747 Mex(线段树+思维题)
- hdu-1166-敌兵布阵-线段树-单点更新,区域查询
- HDU 1166 (线段树--单点更新,区域查询)
- 今日任务2014.5.26
- 保存 XML
- 数字数码管-解题思路及过程
- [JSP][JSTL]页面中调用函数--之${fn:}内置函数、判断字符串是否为空、替换回车符
- NSButton And NSTextField
- hdu-4747-Mex-线段树区域更新
- Scripts:显示数据库中的控制文件dba_controlfiles.sql
- ACM-MST(最小生成树)之Agri-Net——poj1258
- ibatis like查询防sql注入
- 每日算法之十九:Valid Parentheses
- Longest Substring Without Repeating Characters
- iOS中block类型大全
- 01.ViewPager使用Demo
- 2014任重道远的SEO行程