zoukankan      html  css  js  c++  java
  • BZOJ3339&&3585 Rmq Problem&&mex

    BZOJ3339&&3585:Rmq Problem&&mex

    Description

      有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

    Input

      第一行n,m。
      第二行为n个数。
      从第三行开始,每行一个询问l,r。

    Output

      一行一个数,表示每个询问的答案。

    Sample Input

    5 5

    2 1 0 2 1

    3 3

    2 3

    2 4

    1 2

    3 5

    Sample Output

    1

    2

    3

    0

    3

    HINT

    数据规模和约定

      对于(100%)的数据:

      (1leq n,mleq200000)

      (0leq a_ileq10^9)

      (1leq l,rleq n)

      对于(30%)的数据:

      (1leq n,m leq1000)

    题解

    先离散化,注意补充上每个数(+1)(0)
    离线所有询问,按左端点(l)排序。
    不难得到([1,i])的答案
    考虑已知区间([l,r])的答案,如何得到区间([l+1,r])的答案
    这样其实是删除了(a[l])(nxt[l])表示下一个(a[l])出现的位置,所以删除(a[l])影响了([l+1,l+1])([l+1,nxt[l]-1])这些区间。这些区间的(mex)都要对(a[l])(min)
    区间取(min),典型线段树操作。叶子节点的(ma)是值,其余节点(ma)存区间取(min)标记。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <stack>
    #include <cmath>
    #include <string>
    #define abs(x) ((x) < 0 ? -1 * (x) : (x))
    template <class T>
    inline void read(T &x)
    {
        x = 0;char ch = getchar(), c = ch;
        while(ch < '0' || ch > '9') c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
        if(c == '-') x = -x;
    }
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a < b ? a : b;}
    const int INF = 0x3f3f3f3f;
    const int MAXN = 400000 + 10;
    int n,q,num[MAXN],tong[MAXN],nxt[MAXN];
    struct Q
    {
    	int l,r,rank;
    }a[MAXN];
    bool cmp(Q a, Q b)
    {
    	return a.l < b.l;
    }
    struct Node
    {
    	int ma, lazy, l, r;
    	Node(){ma = INF;lazy = -1;}
    }node[MAXN << 3];
    void pushdown(int o)
    {
    	node[o << 1].ma = min(node[o << 1].ma, node[o].ma);
    	node[o << 1 | 1].ma = min(node[o << 1 | 1].ma, node[o].ma);	
    
    } 
    void modify(int ll, int rr, int k, int o = 1, int l = 1, int r = n)
    {
    	pushdown(o);node[o].l = l, node[o].r = r;
    	if(ll <= l && rr >= r)
    	{
    		node[o].ma = min(node[o].ma, k);
    		node[o].lazy = k;
    		return;
    	} 
    	int mid = (l + r) >> 1;
    	if(mid >= ll) modify(ll, rr, k, o << 1, l, mid);
    	if(mid < rr) modify(ll, rr, k, o << 1 | 1, mid + 1, r);
    	return;
    }
    int ask(int p, int o = 1, int l = 1, int r = n)
    {
    	pushdown(o);
    	if(l == r && p == l) return node[o].ma;
    	int mid = (l + r) >> 1;
    	if(p <= mid) return ask(p, o << 1, l, mid);
    	else return ask(p, o << 1 | 1, mid + 1, r);
    }
    int ans[MAXN];
    
    //lisanhua
    int tmp[MAXN], cnt[MAXN], val[MAXN], tot;
    bool cmpp(int a, int b)
    {
    	return tmp[a] < tmp[b];
    }
    
    int main()
    {
    	read(n), read(q);
    	for(int i = 1;i <= n;++ i)
    		read(num[i]), tmp[i] = num[i], cnt[i] = i;
    	std::sort(cnt + 1, cnt + 1 + n, cmpp);num[0] = -1;
    	for(int i = 1;i <= n;++ i)
    	{
    		if(tmp[cnt[i - 1]] != tmp[cnt[i]]) 
    		{
    			++ tot;
    			if(tmp[cnt[i]] - tmp[cnt[i - 1]] > 1) val[tot] = num[cnt[i - 1]] + 1, ++ tot;
    			num[cnt[i]] = tot;
    			val[tot] = tmp[cnt[i]];
    		}
    		else num[cnt[i]] = tot;
    	}
    	val[++ tot] = tmp[cnt[n]] + 1;
    	for(int i = 1;i <= q;++ i)
    		read(a[i].l), read(a[i].r), a[i].rank = i;
    	std::sort(a + 1, a + 1 + q, cmp);
    	int p = 0;
    	for(int i = 1;i <= n;++ i)
    		if(num[i] == p)
    		{
    			tong[p] = 1;
    			while(tong[p]) ++ p;
    			modify(i, i, p);
    		}
    		else tong[num[i]] = 1, modify(i, i, p);
    	memset(tong, 0, sizeof(tong));
    	for(int i = n;i >= 1;-- i) 
    		if(!tong[num[i]]) nxt[i] = n + 1, tong[num[i]] = i;
    		else nxt[i] = tong[num[i]], tong[num[i]] = i;
    	int now = 1;
    	for(int i = 1;i <= q;++ i)
    	{
    		while(now < a[i].l)
    		{
    			modify(now, nxt[now] - 1, num[now]);
    			++ now;
    		}
    		ans[a[i].rank] = ask(a[i].r);
    	}
    	for(int i = 1;i <= q;++ i) printf("%d
    ", val[ans[i]]);
    	return 0;
    }
    
  • 相关阅读:
    20165211 2017-2018-2 《Java程序设计》第1周学习总结
    nginx解析漏洞
    Killable Processes in Oracle Database
    Know more about PGA_AGGREGATE_LIMIT 12c 19c
    mysql查看存储过程函数
    oracle 12.1.0.2升级oracle12.2.0.1(non cdb)
    MySQL 一张表单个索引最多支持创建16个字段
    AWR automatic or manual snapshot hangs – EXADATA
    创建表时报错,索引列超过最大约束
    mysql while 循环
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8470095.html
Copyright © 2011-2022 走看看