zoukankan      html  css  js  c++  java
  • [BZOJ3339] Rmq Problem(线段树)

    传送门

    这个题的方法好像很多啊

    1.莫队暴力

    2.线段树 + 离线处理

    先预处理出sg[i]表示前i个数的sg值,next[i]表示i的下一位置在哪里,如果后面再没有i,那么next[i] = n + 1

    然后把线段树的每个叶子节点放上sg[i]。

    把询问按照左端点由小到大排序,我们考虑如何从 l ~ r 转移到 l + 1 ~ r,

    会发现,当把a[l]这个数去掉之后,如果后面没有a[l]那么答案就可能会更新,

    那么我们可以更新 l + 1 ~ next[l] - 1这个区间,也就是用线段树操作

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #define N 200001
    #define INF ~(1 << 31)
    #define root 1, 1, n
    #define ls now << 1, l, mid
    #define rs now << 1 | 1, mid + 1, r
    #define min(x, y) ((x) < (y) ? (x) : (y))
    
    int n, q;
    int a[N], next[N], vis[N], ans[N], mx[N << 2], sg[N];
    
    struct node
    {
    	int x, y, id;
    }p[N];
    
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    	return x * f;
    }
    
    inline bool cmp(node x, node y)
    {
    	return x.x < y.x;
    }
    
    inline void build(int now, int l, int r)
    {
    	if(l == r)
    	{
    		mx[now] = sg[l];
    		return;
    	}
    	mx[now] = INF;
    	int mid = (l + r) >> 1;
    	build(ls);
    	build(rs);
    }
    
    inline void push_down(int now)
    {
    	if(mx[now] != INF)
    	{
    		mx[now << 1] = min(mx[now << 1], mx[now]);
    		mx[now << 1 | 1] = min(mx[now << 1 | 1], mx[now]);
    		mx[now] = INF;
    	}
    }
    
    inline void update(int now, int l, int r, int x, int y, int d)
    {
    	if(x <= l && r <= y)
    	{
    		mx[now] = min(mx[now], d);
    		return;
    	}
    	push_down(now);
    	int mid = (l + r) >> 1;
    	if(x <= mid) update(ls, x, y, d);
    	if(mid < y) update(rs, x, y, d);
    }
    
    inline int query(int now, int l, int r, int x)
    {
    	if(l == r) return mx[now];
    	push_down(now);
    	int mid = (l + r) >> 1;
    	if(x <= mid) return query(ls, x);
    	else return query(rs, x);
    }
    
    int main()
    {
    	int i, j = 0, now = 1, nxt;
    	n = read();
    	q = read();
    	for(i = 1; i <= n; i++) a[i] = read();
    	for(i = 1; i <= n; i++)
    	{
    		vis[a[i]] = 1;
    		while(vis[j]) j++;
    		sg[i] = j;
    	}
    	build(root);
    	for(i = 0; i <= n; i++) vis[i] = n + 1;
    	for(i = n; i >= 1; i--) next[i] = vis[a[i]], vis[a[i]] = i;
    	for(i = 1; i <= q; i++)
    	{
    		p[i].id = i;
    		p[i].x = read();
    		p[i].y = read();
    	}
    	std::sort(p + 1, p + q + 1, cmp);
    	for(i = 1; i <= q; i++)
    	{
    		while(now < p[i].x)
    		{
    			if(now + 1 < next[now])
    				update(root, now + 1, next[now] - 1, a[now]);
    			now++;
    		}
    		ans[p[i].id] = query(root, p[i].y);
    	}
    	for(i = 1; i <= q; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    

    3.主席树

    。。不会

  • 相关阅读:
    003-2021 java.sql.SQLSyntaxErrorException: Unknown column 'Kitty' in 'where clause'
    002-2021 SpringMVC文件跨服务器上传异常之 409 : 目录不存在
    001-2021 SpringMVC文件跨服务器上传异常之405 : UniformInterfaceException : PUT http://localhost:9090/uploads/xxx returned a response status of 405 Method Not Allowed
    JUnit错误 : java.lang.NoSuchMethodError: org.junit.runner.Description.createSuiteDescription
    char[]
    Sql语句执行与书写顺序
    Java深拷贝和浅拷贝区别
    C++析构函数详解
    浅谈c/c++中register关键字
    C++异常之栈解旋
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7550456.html
Copyright © 2011-2022 走看看