啦啦啦。

这是杭州网赛的一个题目,当时没做出来,当然这个想法确实比较难想到。

题目质量很高,这个题目也很特别,以前都没做过类似的题目。让我又一次体验了线段树的强大力量。

题目的意思是给你n个数a1-an。对于任何一个区间[l,r],它所对应的值为这个区间内没有出现的最小非负整数,求所有1<=L<=R<=n的区间所对应的值的总和。

比赛的时候苦思无果,以为是什么高端的数据结构或者很奇怪的算法,后来才发现自己坑了。

题目其实是这样的,在最开始预处理所有1开头的(即L=1的所有区间的值,然后从1开始每次都删除一个数,并且更新区间,每次都求一次和,然后就没有然后了,把每次更新后的区间所要求的和加起来就是答案了哦。

这个想法是没有错的,但是实现起来十分的麻烦。我也是经历了若干发TLE,WA,RE以后最终内牛满面地A掉了此题,以此作为纪念。

再讲讲具体是怎么实现的吧!其实预处理的话可以用数组模拟链表来实现,时间非常快(就像建图那种方法),但是由于Ai可能给的很大,所以我们用哈希来实现快速查询啊。记录每个数下一次出现的位置。如果没有出现,那么下一次出现的位置为n+1就好了。

假设当前我已经统计好了Ai作为起点的值,现在要统计Ai+1作为起点的值?应该怎么做?怎么更新呢?

是这样的。找到Ai+1下一次出现的地方的前一位。如果它所对应的那个函数值比当前的小,那说明不用更新了(想想问什么?因为说明有比当前数更小的数没有出现,所以无需更新,而在出现以后的地方显然又已经存在Ai在前面了。)

如果那个数的值大于当前的值,则说明可以修改更新。但是在更新前要先查一下从哪一步开始查找,就二分查找啦,找到第一个大于Ai的数。然后更新区间就可以了。

记得每次删除一个数Ai都要把query(i+1,pos)  的值加到ans里面哦。

总的时间复杂度是:n*log(n)*log(n)。Dangerous !!!

上代码吧:(注意用long long)

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#define maxn 200200
#define ll long long
using namespace std; int a[maxn],b[maxn],col[*maxn],next[maxn],cur;
int n,m,k,t,pos;
ll ans,sum[*maxn];
map<int,int> ss;
bool visit[maxn]; void PushDown(int rt,int l,int r)
{
if (col[rt]==-) return;
col[rt<<]=col[rt<<|]=col[rt];
int mid=(l+r)>>;
sum[rt<<]=col[rt]*(mid-l+);
sum[rt<<|]=col[rt]*(r-mid);
col[rt]=-;
} void PushUp(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
} void build(int rt,int l,int r)
{
col[rt]=-;
if (l==r) { sum[rt]=b[l]; return ; }
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
PushUp(rt);
} void update(int rt,int l,int r,int L,int R,int id)
{
if (L>R) return;
if (L<=l && R>=r)
{
sum[rt]=id*(r-l+);
col[rt]=id;
return ;
}
PushDown(rt,l,r);
int mid=(l+r)>>;
if (L<=mid) update(rt<<,l,mid,L,R,id);
if (R> mid) update(rt<<|,mid+,r,L,R,id);
PushUp(rt);
} ll query(int rt,int l,int r,int L,int R)
{
if (L>R) return ;
if (L<=l && R>=r) return sum[rt];
PushDown(rt,l,r);
int mid=(l+r)>>;
ll tot=;
if (L<=mid) tot=query(rt<<,l,mid,L,R);
if (R> mid) tot+=query(rt<<|,mid+,r,L,R);
return tot;
} int find(int l,int r,int id)
{
int mid;
while (l<r)
{
mid=(l+r)>>;
if (query(,,n,mid,mid)<=id) l=mid+;
else r=mid;
}
return l;
} int main()
{
while (scanf("%d",&n) && (n))
{
ss.clear();
for (int i=; i<=n; i++) scanf("%d",&a[i]);
memset(visit,false,sizeof visit);
for (int i=n; i>=; i--)
{
if (ss[a[i]]!=) next[i]=ss[a[i]];
else next[i]=n+;
ss[a[i]]=i;
}
cur=;
for (int i=; i<=n; i++)
{
if (a[i]<maxn) visit[a[i]]=true;
while (visit[cur]) cur++;
b[i]=cur;
}
build(,,n);
ans=sum[];
for (int i=; i<n; i++)
{
pos=min(next[i]-,n);
if (i+<=pos)
if (query(,,n,pos,pos)>a[i])
{
k=find(i+,pos,a[i]);
update(,,n,k,pos,a[i]);
}
ans+=query(,,n,i+,n);
}
printf("%I64d\n",ans);
}
return ;
}

HDU4747——2013 ACM/ICPC Asia Regional Hangzhou Online的更多相关文章

  1. hdu 4747 Mex (2013 ACM/ICPC Asia Regional Hangzhou Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 思路: 比赛打得太菜了,不想写....线段树莽一下 实现代码: #include<iost ...

  2. [2013 ACM/ICPC Asia Regional Hangzhou Online J/1010]hdu 4747 Mex (线段树)

    题意: + ;];;;], seg[rt <<  | ]);)) * fa.setv;) * fa.setv;;], seg[rt <<  | ], r - l + );;,  ...

  3. 2013 ACM/ICPC Asia Regional Hangzhou Online hdu4739 Zhuge Liang's Mines

    Zhuge Liang's Mines Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  4. HDU4745——Two Rabbits——2013 ACM/ICPC Asia Regional Hangzhou Online

    这个题目虽然在比赛的时候苦思无果,但是赛后再做就真的是个水题,赤果果的水题. 题目的意思是给n个数构成的环,两只兔子从任一点开始分别顺逆时针跳,每次可以调到任意一个数(最多不会跳过一圈). 求最多能跳 ...

  5. HDU 4745 Two Rabbits(最长回文子序列)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Description Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon ...

  6. HDU 4744 Starloop System(最小费用最大流)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Description At the end of the 200013 th year of the Galaxy era, the war between Carbon-based lives a ...

  7. HDU 4747 Mex(线段树)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Problem Description Mex is a function on a set of integers, which is universally used for impartial ...

  8. hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Ot ...

  9. hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...

随机推荐

  1. 20155301 2016-2017-2 《Java程序设计》第10周学习总结

    20155301 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 计算机网络: 1.在计算机网络中,现在命名IP地址的规定是IPv4协议,该协议规定每个IP ...

  2. tkinter界面卡死的解决办法

    0.如果点击按钮,运行了一个比较耗时的操作,那么界面会卡死 import tkinter as tk import time def onclick(text, i): time.sleep(3) t ...

  3. springboot中maven加入本地jar

    一.今天遇到一个问题,在使用springboot打jar的时候出现了本地依赖包打不进去的情况.然后在网上试了很多方式.这里做一个记录 二.加入本地依赖包 <dependency> < ...

  4. Yii 2.0 使用验证码

    Yii2.0 提供了验证码组件.调用起来比较方便.以登录页面添加验证码为例. 1. 模型中添加字段和验证规则. common\models\LoginForm 添加如下代码 public $captc ...

  5. itop4412学习-上层应用多任务开发

    1. 首先搭建虚拟机VMWARE12.0+UBUNTU16.04,不过报错了,说是要关闭计算机(非重启)-- 进入BIOS -- 设置BIOS的虚拟化(不打开,默认是工作在32位模式的,virtual ...

  6. 《Node.js 包教不包会》

    <Node.js 包教不包会> 为何写作此课程 在 CNode(https://cnodejs.org/) 混了那么久,解答了不少 Node.js 初学者们的问题.回头想想,那些问题所需要 ...

  7. 「日常训练」Jongmah(Codeforces-1110D)

    题意 你有n个数字,范围[1, m],你可以选择其中的三个数字构成一个三元组,但是这三个数字必须是连续的或者相同的,每个数字只能用一次,问这n个数字最多构成多少个三元组? 分析 根据官方Editori ...

  8. python爬取淘宝华为手机

    import re from selenium import webdriver from selenium.common.exceptions import TimeoutException fro ...

  9. EasyUI tree 优化--点击文字折叠展开效果

    $(function () { $('#tree_menu').tree({ onSelect: function (node) { if (node.state == "closed&qu ...

  10. 技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列

    本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取 货真价值的才貌双全,别人家的孩子 高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零, ...