HDU-4747 二分+线段树
题意:给出长度为n的序列,问任两个区间的mex运算结果的总和。
解法:直接讲线段树做法:我们注意到mex(1,1),mex(1,2),mex(1,3)...mex(1,i)的结果是单调不减的,那么我们考虑先用线段树维护上诉结果,那么此时以1为左端点的区间mex和就求出来了,重点来了:我们考虑怎么从以1为左端点的区间结果过渡到以2为结点的区间结果呢?我们注意到其实只要以1为端点的区间去掉a[1]这个点的影响就可以得到以2为端点的区间结果,那么我们怎样去除a[1]这个点的影响呢?我们发现去掉a[1]之后会影响到的就是位置1到下一个a[1]出现位置的这一段区间!这一段区间的结果如果mex>a[1],那么因为a[1]的删除它的结果就会变成a[1]。且我们上面提到mex(1,1)到mex(1,n)的结果是单调不减的。那么我们就可以在线段树上二分来找一个mex>a[1]的点,区间修改即可。这样下去一边统计答案一边删除数修改影响,到最后就可以AC了。
这道题的线段树解法还是比较经典的做法的,对于一类问题:询问的是任两个区间的结果总和,而且发现我们能比较快速地通过删除最前面的数使得结果快速过渡到下一个区间的结果,那么我们可以考虑使用这种像前缀线段树(这个简称是蒟蒻瞎掰的qwq)的做法。
细节详见代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+;
int n,a[N],f[N],nxt[N];
bool vis[N];
map<int,int> mp; LL sum[N<<],tag[N<<];
void pushup(int rt) {
sum[rt]=sum[rt<<]+sum[rt<<|];
}
void pushdown(int rt,int l1,int l2) {
if (tag[rt]==-) return;
sum[rt<<]=(LL)tag[rt]*l1; tag[rt<<]=tag[rt];
sum[rt<<|]=(LL)tag[rt]*l2; tag[rt<<|]=tag[rt];
tag[rt]=-;
}
void build(int rt,int l,int r) {
if (l==r) {
sum[rt]=f[l]; tag[rt]=-;
return;
}
sum[rt]=; tag[rt]=-;
int mid=l+r>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushup(rt);
}
void update(int rt,int l,int r,int ql,int qr,int v) {
if (ql<=l && r<=qr) {
sum[rt]=(LL)v*(r-l+); tag[rt]=v;
return;
}
int mid=l+r>>;
pushdown(rt,mid-l+,r-mid);
if (ql<=mid) update(rt<<,l,mid,ql,qr,v);
if (qr>mid) update(rt<<|,mid+,r,ql,qr,v);
pushup(rt);
}
LL query(int rt,int l,int r,int ql,int qr) {
if (ql<=l && r<=qr) return sum[rt];
int mid=l+r>>;
pushdown(rt,mid-l+,r-mid);
LL ret=;
if (ql<=mid) ret+=query(rt<<,l,mid,ql,qr);
if (qr>mid) ret+=query(rt<<|,mid+,r,ql,qr);
return ret;
} int main()
{
while (scanf("%d",&n) && n) {
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=n;i++) vis[i]=;
for (int i=;i<=n;i++) {
if (a[i]<=n) vis[a[i]]=;
f[i]=f[i-];
while (vis[f[i]]) f[i]++;
}
mp.clear();
for (int i=n;i;i--) {
if (mp.count(a[i])) nxt[i]=mp[a[i]]; else nxt[i]=n+;
mp[a[i]]=i;
}
build(,,n);
LL ans=;
for (int i=;i<=n;i++) {
ans+=query(,,n,i,n);
int l=i,r=nxt[i]-,t=a[i];
while (l<r) {
int mid=l+r>>;
if (query(,,n,mid,mid)>t) r=mid; else l=mid+;
}
if (query(,,n,r,r)>t)
update(,,n,r,nxt[i]-,a[i]);
}
printf("%lld\n",ans);
}
return ;
}
HDU-4747 二分+线段树的更多相关文章
- hdu 4747 mex 线段树+思维
http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意: 我们定义mex(l,r)表示一个序列a[l]....a[r]中没有出现过得最小的非负整数, 然后我 ...
- hdu 4747【线段树-成段更新】.cpp
题意: 给出一个有n个数的数列,并定义mex(l, r)表示数列中第l个元素到第r个元素中第一个没有出现的最小非负整数. 求出这个数列中所有mex的值. 思路: 可以看出对于一个数列,mex(r, r ...
- HDU 6070 二分+线段树
Dirt Ratio Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Tot ...
- hdu 4747 Mex( 线段树? 不,区间处理就行(dp?))
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- HDU 4747 Mex ( 线段树好题 + 思路 )
参考:http://www.cnblogs.com/oyking/p/3323306.html 相当不错的思路,膜拜之~ 个人理解改日补充. #include <cstdio> #incl ...
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- hdu 4031 attack 线段树区间更新
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Subm ...
- hdu 4288 离线线段树+间隔求和
Coder Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
随机推荐
- 在eclipse中添加svn插件
1.点击菜单栏中的help选项,然后选择Install New Software,然后点击ADD,输入: name:subclipse url:http://subclipse.tigris. ...
- java延迟队列
大多数用到定时执行的功能都是用任务调度来做的,单身当碰到类似订餐业务/购物等这种业务就不好处理了,比如购物的订单功能,在你的订单管理中有N个订单,当订单超过十分钟未支付的时候自动释放购物车中的商品,订 ...
- centos 升级python
1.下载python3.6.1的包 wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz 2.解压 tar -zxvf Pytho ...
- hadoop 2.7 添加或删除datanode节点
1.测试环境 ip 主机名 角色 10.124.147.22 hadoop1 namenode 10.124.147.23 hadoop2 namenode 10.124.147.32 hadoop3 ...
- MyBatis注解开发-@Insert和@InsertProvider(@Select、@SelectProvider雷同)
@Insert和@InsertProvider都是用来在实体类的Mapper类里注解保存方法的SQL语句.不同的是,@Insert是直接配置SQL语句,而@InsertProvider则是通过SQL工 ...
- shell 以指定字符拆分字符串
string="hell|ttt|sss|2222" OLD_IFS="$IFS" IFS="|" array=($string) IFS= ...
- Mac上的Apache 开启,停止,重启
sudo apachectl -k start 启动 sudo apachectl -k stop 停止 sudo apachectl -k restart 重启
- java html生成PDF,并打印
import java.io.File; import java.io.FileOutputStream; import org.zefer.pd4ml.PD4Constants; import or ...
- Mybatis基于接口注解配置SQL映射器(二)
Mybatis之增强型注解 MyBatis提供了简单的Java注解,使得我们可以不配置XML格式的Mapper文件,也能方便的编写简单的数据库操作代码.但是注解对动态SQL的支持一直差强人意,即使My ...
- mysql性能查看 命中率 慢查询
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...