mex性质学习

E.Complicated Computations

如果一个区间的mex=amex=amex=a,满足以下条件:

  • 区间未出现aaa
  • 区间出现1→a−11\to a-11a1

因此若考虑是否存在一个区间的mex值是aaa,我们尝试把整个区间以aaa为端点划分成若干段,只要每一段内(不含端点a)中出现1→a−11\to a-11a1那么就存在一个区间的mex值是aaa
a…a…a…a…a…a…aa\dots a\dots a\dots a\dots a\dots a\dots aaaaaaaa
即只要有一个…\dots存在1→a−11\to a-11a1那么就存在区间mex=amex=amex=a

那么如何确定…\dots存在1→a−11\to a-11a1
不妨假设两个a的位置一个是LLL,一个是RRR,那么我们现在判定[L+1,R−1][L+1,R-1][L+1,R1]的区间是否存在1→a−11\to a-11a1。那么不难发现1→a−11\to a-11a1最后一次出现的位置>L>L>L
由此用权值线段树维护每一个数最后一次出现的位置,并且记录上一次某数出现的位置查询即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=100010;
int a[N],n;
bool st[N];
int last[N];
int pos[N<<2];
void modify(int u,int l,int r,int k,int x)
{if(l==r) {pos[u]=x;return;}int mid=l+r>>1;if(k<=mid) modify(u<<1,l,mid,k,x);else modify(u<<1|1,mid+1,r,k,x);pos[u]=min(pos[u<<1],pos[u<<1|1]);
}
int query(int u,int l,int r,int L,int R)
{if(l>=L&&r<=R) return pos[u];int mid=l+r>>1;if(R<=mid)return query(u<<1,l,mid,L,R);else if(L>mid)return query(u<<1|1,mid+1,r,L,R);else return min(query(u<<1,l,mid,L,R),query(u<<1|1,mid+1,r,L,R));
}
int main()
{IO;int T=1;//cin>>T;for(int ca=1;ca<=T;ca++){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++){if(a[i]!=1) st[1]=1;if(a[i]>1&&query(1,1,n,1,a[i]-1)>last[a[i]]) st[a[i]]=1;last[a[i]]=i;modify(1,1,n,a[i],i);}for(int i=2;i<=n+1;i++) //枚举到n+1有可能有区间的mex=n+1if(query(1,1,n,1,i-1)>last[i]) st[i]=1;int res=1;while(st[res]) res++;cout<<res<<'\n';}return 0;
}

这题竟然还卡时间?用build版本的线段树就TLE,只能查询时传递区间。。。

本题还可以效仿下面题目的做法,用线段树维护mex,每次区间修改aia_iai 时便可能存在区间的mex是 aia_iai

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=200010;
int a[N],n;
int mex[N],ne[N],pos[N];
bool st[N];
struct node
{int l,r;ll tag;ll mn,mx;
}t[N<<2];
void pushup(int u)
{t[u].mn=min(t[u<<1].mn,t[u<<1|1].mn);t[u].mx=max(t[u<<1].mx,t[u<<1|1].mx);
}
void build(int u,int l,int r)
{t[u]={l,r,-1,0x3f3f3f3f,-0x3f3f3f3f};if(l==r){t[u].mn=t[u].mx=mex[l]; return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void pushdown(int u)
{if(t[u].tag==-1) return;t[u<<1].tag=t[u].tag;t[u<<1|1].tag=t[u].tag;t[u<<1].mn=t[u].tag;t[u<<1|1].mn=t[u].tag;t[u<<1].mx=t[u].tag;t[u<<1|1].mx=t[u].tag;t[u].tag=-1;
}
bool modify(int u,int l,int r,int x)
{if(l>r) return 0;if(t[u].mx<=x) return 0;if(t[u].l>=l&&t[u].r<=r&&t[u].mn>x){t[u].tag=x;t[u].mn=x;t[u].mx=x;return 1;}pushdown(u);int mid=t[u].l+t[u].r>>1;bool ok=0;if(l<=mid) ok|=modify(u<<1,l,r,x);if(r>mid)  ok|=modify(u<<1|1,l,r,x);pushup(u);return ok;
}int vis[N];int main()
{scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);int now=1;for(int i=1;i<=n;i++){st[a[i]]=1;while(st[now]) now++;mex[i]=now;vis[now]=1;}//for(int i=1;i<=n;i++) cout<<mex[i]<<' ';cout<<'\n';for(int i=0;i<=n+1;i++) pos[i]=n+1;for(int i=n;i;i--){ne[i]=pos[a[i]];pos[a[i]]=i;}build(1,1,n);for(int i=1;i<=n;i++){int l=i+1,r=ne[i]-1;if(modify(1,l,r,a[i])) vis[a[i]]=1;}//for(int i=1;i<=n;i++) cout<<vis[i]<<' ';cout<<'\n';int res=1; while(vis[res]) res++;printf("%d\n",res);return 0;
}

Hdu. Mex

大佬题解
mex(1,i)mex(1,i)mex(1,i)具有单调递增的性质。

#include<bits/stdc++.h>#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=200010;
int a[N],n;
int mex[N],ne[N],pos[N];
bool st[N];
struct node
{int l,r;ll s;ll lazy;
}tree[N<<2];
void pushup(int u)
{tree[u].s=tree[u<<1].s+tree[u<<1|1].s;
}
void build(int u,int l,int r)
{tree[u]={l,r,0,-1};if(l==r){tree[u].s=mex[l]; return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void pushdown(int u)
{if(tree[u].lazy==-1) return;int lenl=tree[u<<1].r-tree[u<<1].l+1;int lenr=tree[u<<1|1].r-tree[u<<1|1].l+1;tree[u<<1].s=1ll*lenl*tree[u].lazy;tree[u<<1|1].s=1ll*lenr*tree[u].lazy;tree[u<<1].lazy=tree[u].lazy;tree[u<<1|1].lazy=tree[u].lazy;tree[u].lazy=-1;
}
void modify(int u,int l,int r,int x)
{if(tree[u].l>=l&&tree[u].r<=r){tree[u].s=1ll*x*(tree[u].r-tree[u].l+1);tree[u].lazy=x;return;}pushdown(u);int mid=tree[u].l+tree[u].r>>1;if(l<=mid) modify(u<<1,l,r,x);if(r>mid) modify(u<<1|1,l,r,x);pushup(u);
}
ll query(int u,int l,int r)
{if(tree[u].l>=l&&tree[u].r<=r) return tree[u].s;pushdown(u);int mid=tree[u].l+tree[u].r>>1;ll v=0;if(l<=mid) v+=query(u<<1,l,r);if(r>mid) v+=query(u<<1|1,l,r);return v;
}
int main()
{while(scanf("%d",&n),n){for(int i=1;i<=n;i++){scanf("%d",&a[i]);if(a[i]>n) a[i]=n+1;}for(int i=0;i<=n+1;i++) st[i]=0;int now=0;for(int i=1;i<=n;i++){st[a[i]]=1;while(st[now]) now++;mex[i]=now;}for(int i=0;i<=n+1;i++) pos[i]=n+1;for(int i=n;i;i--){ne[i]=pos[a[i]];pos[a[i]]=i;}build(1,1,n);ll res=0;for(int i=1;i<=n;i++){res+=query(1,i,n);int l=i,r=ne[i]-1;while(l<r){int mid=l+r>>1;if(query(1,mid,mid)>a[i]) r=mid;else l=mid+1;}if(query(1,l,l)>a[i]) modify(1,l,ne[i]-1,a[i]);}printf("%lld\n",res);}return 0;
}

同时维护最大最小值,势能去掉二分

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=200010;
int a[N],n;
int mex[N],ne[N],pos[N];
bool st[N];
struct node
{int l,r;ll s;ll tag;ll mn,mx;
}t[N<<2];
void pushup(int u)
{t[u].s=t[u<<1].s+t[u<<1|1].s;t[u].mn=min(t[u<<1].mn,t[u<<1|1].mn);t[u].mx=max(t[u<<1].mx,t[u<<1|1].mx);
}
void build(int u,int l,int r)
{t[u]={l,r,0,-1,0x3f3f3f3f,-0x3f3f3f3f};if(l==r){t[u].s=t[u].mn=t[u].mx=mex[l]; return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void pushdown(int u)
{if(t[u].tag==-1) return;int lenl=t[u<<1].r-t[u<<1].l+1;int lenr=t[u<<1|1].r-t[u<<1|1].l+1;t[u<<1].s=1ll*lenl*t[u].tag;t[u<<1|1].s=1ll*lenr*t[u].tag;t[u<<1].tag=t[u].tag;t[u<<1|1].tag=t[u].tag;t[u<<1].mn=t[u].tag;t[u<<1|1].mn=t[u].tag;t[u<<1].mx=t[u].tag;t[u<<1|1].mx=t[u].tag;t[u].tag=-1;
}
void modify(int u,int l,int r,int x)
{if(t[u].mx<=x) return;if(t[u].l>=l&&t[u].r<=r&&t[u].mn>x){t[u].s=1ll*x*(t[u].r-t[u].l+1);t[u].tag=x;t[u].mn=x;t[u].mx=x;return;}pushdown(u);int mid=t[u].l+t[u].r>>1;if(l<=mid) modify(u<<1,l,r,x);if(r>mid)  modify(u<<1|1,l,r,x);pushup(u);
}
ll query(int u,int l,int r)
{if(t[u].l>=l&&t[u].r<=r) return t[u].s;pushdown(u);int mid=t[u].l+t[u].r>>1;ll v=0;if(l<=mid) v+=query(u<<1,l,r);if(r>mid) v+=query(u<<1|1,l,r);return v;
}
int main()
{while(scanf("%d",&n),n){for(int i=1;i<=n;i++){scanf("%d",&a[i]);if(a[i]>n) a[i]=n+1;}for(int i=0;i<=n+1;i++) st[i]=0;int now=0;for(int i=1;i<=n;i++){st[a[i]]=1;while(st[now]) now++;mex[i]=now;}for(int i=0;i<=n+1;i++) pos[i]=n+1;for(int i=n;i;i--){ne[i]=pos[a[i]];pos[a[i]]=i;}build(1,1,n);ll res=0;for(int i=1;i<=n;i++){res+=query(1,i,n);int l=i,r=ne[i]-1;if(l<=r) modify(1,l,r,a[i]);}printf("%lld\n",res);}return 0;
}

在这里插入图片描述
两者时间复杂度对比,效果还挺明显。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319364.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cows

题目 题意: 有一群牛&#xff0c;每个牛有两个属性值[S,E]&#xff0c;如果牛i和牛j属性值满足Si < Sj 且 Ej < Ei 且 Ei - Si > Ej - Sj&#xff0c;牛i比牛j强壮&#xff0c;输出每个牛比自己强壮的牛的数量。 题解&#xff1a; 我们可以把[S,E]看作坐标&#x…

【SAM】差异(P4248)

正题 P4248 题目大意 设TiT_iTi​为第i个字符开始的后缀&#xff0c;求&#xff1a; ∑i1n∑ji1nlen(Ti)len(Tj)−2lcp(Ti,Tj)\sum_{i1}^n \sum_{ji1}^n len(T_i)len(T_j)-2\times lcp(T_i,T_j)i1∑n​ji1∑n​len(Ti​)len(Tj​)−2lcp(Ti​,Tj​) 解题思路 用SAM建立paren…

P4345-[SHOI2015]超能粒子炮·改【Lucas定理,类欧】

正题 题目链接:https://www.luogu.com.cn/problem/P4345 题目大意 TTT组询问&#xff0c;给出n,kn,kn,k求 ∑i0k(ni)\sum_{i0}^{k}\binom{n}{i}i0∑k​(in​) 对233323332333取模的值 1≤T≤105,1≤k≤n≤10181\leq T\leq 10^5,1\leq k\leq n\leq 10^{18}1≤T≤105,1≤k≤n≤1…

AServer - 基于Asp.net core Kestrel的超迷你http服务器

AServer是基于ASP.NET Core Kestrel封装的一个超迷你http服务器。它可以集成进你的Core程序里&#xff0c;用来快速的响应Http请求&#xff0c;而不需要集成整个ASP.NET Core MVC 框架。一&#xff1a;什么是ASever&#xff1f;AServer就像它的名字一样&#xff0c;Just a serv…

特征根是复数的二阶微分方程

考虑如下微分方程d2ydx2a1dydxa2x0\frac{d^2y}{dx^2}a_1\frac{dy}{dx}a_2x0dx2d2y​a1​dxdy​a2​x0 众所周知&#xff0c;一般求得二阶常系数线性微分方程的通常由以下步骤 根据微分方程写出它的特征方程λ2a1λa20\lambda^2a_1\lambdaa_20λ2a1​λa2​0求解特征方程的两个…

Buy and Resell 2018中国大学生程序设计竞赛 - 网络选拔赛

题目 题意&#xff1a; n个宝石&#xff0c;宝石的买入或卖出价格固定&#xff0c;一天只能到一个珠宝商店&#xff08;从左到右&#xff09;&#xff0c;问最大利润是多少&#xff1f;在保证最大利润的同时最少交换次数是多少&#xff1f; 题解&#xff1a; 题目有两问&am…

基于Service fabric + Ocelot + Identity Server4 + 52ABP 的案例展示

10.24-27 大会Microsoft Tech Summit 2018 在上海举办&#xff0c;我 有幸受邀成为这场大会的讲师。Microsoft Tech Summit 2018 微软技术暨生态大会将于10月24日至27日在上海世博中心举行&#xff0c;这也会是国内举办的最后一届 Tech Summit&#xff0c;2019 年开始会以 Micr…

【网络流】植物大战僵尸(P2805)

正题 P2805 题目大意 在一个nmn\times mnm的平面上有若干植物&#xff0c;每个植物有其攻击集合&#xff0c;吃掉一个植物要先吃掉该植物右边的所有植物&#xff0c;且该植物不能在任何一个植物的攻击集合内&#xff0c;吃掉后有贡献ai,ja_{i,j}ai,j​&#xff0c;问你最大贡…

YbtOJ#763-攻城略池【线段树合并】

正题 题目链接:http://www.ybtoj.com.cn/problem/763 题目大意 给出nnn个点的一棵树&#xff0c;每个di0d_i0di​0的点每秒会产生一个士兵往根节点走&#xff0c;走到一个节点让一个节点did_idi​减一&#xff08;为000就不管&#xff09;。 求需要多久才能让所有点的ddd值变…

ARC106——E - Medals

E - Medals 首先看到这题看不出是一个匹配的题大佬题解 把每一个工人和每一天看成一个二分图&#xff0c;如果某个工人在某天工作&#xff0c;那么两者存在边&#xff0c;现在问题转化成至少需要多少天&#xff0c;能够把nnn个工人全部匹配kkk次 显然天数可以二分&#xff0…

2020 CCPC网络赛 赛后感

第一次参加&#xff0c;做过去年19年网络赛的题&#xff0c;去年是四个水题稳做出&#xff0c;然后还有两个线段树和树状数组的题&#xff08;好像是&#xff09;&#xff0c;所以本来对这次网络赛挺有信心的&#xff08;去年好像四个题就能进,当然要手速快&#xff09;。 这次…

Feature Flag 功能发布控制

背景产品在新功能发布前&#xff0c;可能会采取小流量测试的方式&#xff0c;或者在确定方案前使用A/B测试来衡量。一般开发人员会跟运维同学合作&#xff0c;通过一些现有平台切换机器或者流量来实现。本文介绍了另外一种简便的方式&#xff0c;并解释了其在持续集成上的应用&…

P4542-[ZJOI2011]营救皮卡丘【费用流,Floyd】

正题 题目链接:https://www.luogu.com.cn/problem/P4542 题目大意 给出n1n1n1个点mmm条边的无向图&#xff0c;kkk个人开始在000号点&#xff0c;一个人进入iii号点之前必须要有人经过i−1i-1i−1号点&#xff0c;求第一个人进入nnn号点时所有人的最短移动距离和。 1≤n≤150…

【线段树】GSS5 - Can you answer these queries V(luogu-SPOJ 2916)

正题 luogu-SPOJ 2916 题目大意 给你一个序列&#xff0c;有若干询问&#xff0c;每次给出左右端点的区间&#xff0c;问你最大字段和 解题思路 用线段树维护区间信息&#xff0c;询问的区间如果有交则分类讨论求解 code #include<cstdio> #include<cstring> #…

SmartSql 动态代理仓储

SmartSql源码&#xff1a;https://github.com/Ahoo-Wang/SmartSql1|1简介动态代理仓储(SmartSql.DyRepository)组件是SmartSql非常独特的功能&#xff0c;它能简化SmartSql的使用。对业务代码除了配置几乎没有侵入。可以说使用SmartSqlContainer是原始方法&#xff0c;而DyRepo…

HDU 6889 Graph Theory Class(CCPC网络赛)

hdu 6889 传说中的人均min25 题意&#xff1a; n个点的完全图&#xff0c;边权为lcm(i1,j1)&#xff0c;求mst&#xff08;最小生成树&#xff09; 题解&#xff1a; 我一开始以为是推公式&#xff0c;毕竟数据范围这么大&#xff0c;但是自己画图来看看mst的情况 注意求lc…

Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据

本来这篇文章在昨天晚上就能发布的&#xff0c;悲剧的是写了两三千字的文章居然没保存&#xff0c;结果我懵逼了。今天重新来写这篇文章。今天我们就一起来探讨下如何重写Ocelot配置文件的存储方式以及获取方式。作者&#xff1a;依乐祝原文地址&#xff1a;https://www.cnblog…

【线段树】蝴蝶与花(P6859)

正题 P6859 题目大意 给你一个由1,2组成的序列&#xff0c;要求完成写下列操作&#xff1a; 修改一个数查找一段区间&#xff0c;使其区间和为s&#xff08;输出左端点最小的一组&#xff09; 解题思路 用线段树来维护该序列&#xff0c;对于每次查询&#xff0c;先找到从1…

YbtOJ#912-神秘语言【结论,欧拉定理】

正题 题目链接:http://www.ybtoj.com.cn/problem/912 题目大意 给出L,RL,RL,R&#xff0c;求有多少长度在[L,R][L,R][L,R]之间的字符串满足依次取出所有偶数位置的放在最前面后&#xff0c;与原字符串相同。字符集是所有小写字母。 1≤Q≤5,1≤L≤R≤1010,R−L≤51041\leq Q\…

path hdu6705

题意&#xff1a; 一个有向加权图&#xff0c;问所有路径汇中第k小的路径长度是多少&#xff1f; 注意一个边可以反复走多次 题解 做法参考 我们可以利用优先队列来做 利用优先队列实现每次所取为最短边 我们假设一条路是从u—>v,路径和为sum&#xff0c;u->v是u的所以…