HDU 4747 Mex (2013杭州网络赛1010题,线段树)★

转载 2016年08月31日 12:45:57

题目定义了mex(i,j)表示,没有在i到j之间出现的最小的非负整数。

求所有组合的i,j(i<=j)的和

就是求mex(1,1) + mex(1,2)+....+mex(1,n)

+mex(2,2) + mex(2,3) + ...mex(2,n)

+mex(3,3) + mex(3,4)+...+mex(3,n)

+ mex(n,n)

可以知道mex(i,i),mex(i,i+1)到mex(i,n)是递增的。

首先很容易求得mex(1,1),mex(1,2)......mex(1,n)

因为上述n个数是递增的。

然后使用线段树维护,需要不断删除前面的数。

比如删掉第一个数a[1]. 那么在下一个a[1]出现前的 大于a[1]的mex值都要变成a[1]

因为是单调递增的,所以找到第一个 mex > a[1]的位置,到下一个a[1]出现位置,这个区间的值变成a[1].

然后需要线段树实现区间修改和区间求和。

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 100100
#define MOD 1000000007

struct node
{
    int l,r;
    long long sum;
    int mx,lazy;
} tree[maxn*6];
int a[maxn<<1],nxt[maxn<<1];
map<int,int> mp;
int n,mex[maxn<<1];

void pushup(int pos)
{
    if(tree[pos].l == tree[pos].r)
        return;
    tree[pos].sum = tree[pos<<1].sum + tree[pos<<1|1].sum;
    tree[pos].mx = max(tree[pos<<1].mx,tree[pos<<1|1].mx);
}
void pushdown(int pos)
{
    if(tree[pos].l == tree[pos].r)
        return;
    if(!tree[pos].lazy)
        return;
    long long k = (long long)tree[pos].mx;
    tree[pos<<1].sum = k*(tree[pos<<1].r - tree[pos<<1].l + 1);
    tree[pos<<1].mx = k;
    tree[pos<<1].lazy = 1;
    tree[pos<<1|1].sum = k*(tree[pos<<1|1].r - tree[pos<<1|1].l + 1);
    tree[pos<<1|1].mx = k;
    tree[pos<<1|1].lazy = 1;
    tree[pos].lazy = 0;
}
void build(int pos,int l,int r)
{
    tree[pos].l = l;
    tree[pos].r = r;
    tree[pos].lazy = 0;
    if(l == r)
    {
        tree[pos].mx = mex[l];
        tree[pos].sum = mex[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(pos<<1,l,mid);
    build(pos<<1|1,mid+1,r);
    pushup(pos);
}
void update(int pos,int l,int r,int v)
{
    if(tree[pos].l == l && tree[pos].r == r)
    {
        tree[pos].sum = (long long)v*(tree[pos].r - tree[pos].l + 1);
        tree[pos].mx = (long long)v;
        tree[pos].lazy = 1;
        return ;
    }
    pushdown(pos);
    int mid = (tree[pos].l + tree[pos].r) >> 1;
    if(r <= mid)
        update(pos<<1,l,r,v);
    else if(l > mid)
        update(pos<<1|1,l,r,v);
    else
    {
        update(pos<<1,l,mid,v);
        update(pos<<1|1,mid+1,r,v);
    }
    pushup(pos);
}
int query(int pos,int v)
{
    if(tree[pos].l == tree[pos].r)
        return tree[pos].l;
    pushdown(pos);
    if(tree[pos<<1].mx > v)
        return query(pos<<1,v);
    else
        return query(pos<<1|1,v);
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t,C = 1;
    //scanf("%d",&t);
    while(scanf("%d",&n) && n)
    {
        for(int i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        mp.clear();
        int tmp = 0;
        for(int i = 1; i <= n; i++)
        {
            mp[a[i]] = 1;
            while(mp.find(tmp) != mp.end())
                tmp++;
            mex[i] = tmp;
        }
        mp.clear();
        for(int i = n; i >= 1; i--)
        {
            if(mp.find(a[i]) == mp.end())
                nxt[i] = n + 1;
            else
                nxt[i] = mp[a[i]];
            mp[a[i]] = i;
        }
        build(1,1,n);
        long long sum = 0;
        for(int i = 1; i <= n; i++)
        {
            sum += tree[1].sum;
            if(tree[1].mx > a[i])
            {
                int l = query(1,a[i]);
                int r = nxt[i];
                if(l < r)
                    update(1,l,r-1,a[i]);
            }
            update(1,i,i,0);
        }
        printf("%lld\n",sum);
    }
    return 0;
}


HDU 4747 Mex (线段树)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出一个序列,mex{}表示集合中没有出现...
  • ACM_cxlove
  • ACM_cxlove
  • 2013年09月16日 22:52
  • 5785

hdu 4747 Mex(线段树)

Mex Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Sub...
  • u010527492
  • u010527492
  • 2014年04月30日 13:36
  • 429

HDU 4747 Mex (线段树)

#include #include #include #include using namespace std; #define ll long long #define prt(k) cerr
  • u011788531
  • u011788531
  • 2014年11月19日 17:08
  • 1032

hdu 4747 Mex(线段树)

将所有的数换种写法 mex = mex(1,1)+mex(1,2)+...+mex(1,n)+mex(2,2)+...+mex(2,n)+...mex(n,n). 应该知道如何算出...
  • u010709592
  • u010709592
  • 2014年03月28日 00:44
  • 787

HDU 4747 Mex(线段树+思维题)

Problem Description Mex is a function on a set of integers, which is universally used for impartial...
  • elbadaernu
  • elbadaernu
  • 2017年12月08日 22:40
  • 46

hdu4747 Mex 线段树 (2013网络赛)

题意:给你一个序列,让你求出对于所有区间的mex和,mex表示该区间没有出现过的最小的整数。 思路:从时限和点数就可以看出是线段树,并且我们可以枚举左端点i, 然后求出所有左端点为i的区间内mex值的...
  • c3568
  • c3568
  • 2013年09月18日 13:25
  • 1286

hdu - 4747 - Mex(二分+线段树)

题意:有一个序列a[],mex(L, R)表示区间a在区间[L, R]上第一个没出现的最小非负整数,对于序列a[],求所有的mex(L, R)的和(1 题目链接:http://acm.hdu.edu...
  • SCNU_Jiechao
  • SCNU_Jiechao
  • 2013年09月18日 12:51
  • 1322

kuangbin带我飞 专题七 线段树专题(一波线段树水题,难题还不会做)

第一次学习线段树,树状数组RMQ等,努力学习,加油。 HDU 1166 题意:很清楚吧 题解:用树状数组求连续和,非常快。 #include #include #include #include...
  • Miracle_ma
  • Miracle_ma
  • 2015年07月09日 13:42
  • 1606

2017多校训练赛第一场 HDU 6039 Gear Up(线段树+并查集)

这题其实没有想象中的那么难,只是当时没有时间去想清楚。         大致题意:给你一些齿轮,有些齿轮是共边(即线速度相同),有些齿轮是共轴(即角速度相同),每个齿轮都有自己的半径而且大小都是2的次...
  • u013534123
  • u013534123
  • 2017年07月26日 14:34
  • 625

hihoCoder[Offer收割]编程练习赛3题目解析

题目1 : hiho密码 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho根据最近在密码学课上学习到的知识,开发出了一款hiho密码,这款密码的秘钥是这样生成的:对...
  • qq_32400847
  • qq_32400847
  • 2016年04月06日 19:31
  • 658
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 4747 Mex (2013杭州网络赛1010题,线段树)★
举报原因:
原因补充:

(最多只允许输入30个字)