zoukankan      html  css  js  c++  java
  • [BZOJ 1058] [ZJOI2007] 报表统计 【平衡树】

    题目链接:BZOJ - 1058

    题目分析

    这道题看似是需要在序列中插入一些数字,但其实询问的内容只与相邻的元素有关。

    那么我们只要对每个位置维护两个数 Ai, Bi, Ai 就是初始序列中 i 这个位置的数, Bi 是在 i 这个位置insert的最后一个数。

    那么在 i insert一个数 Num 的时候,造成的影响就是使得 Bi 和 A(i+1) 不再相邻,同时使 Bi 与 Num, Num 与 A(i+1) 相邻。然后将 Bi 更新为 Num。

    这样就只需要实现一个multiset的功能就可以了。可以手写平衡树,也可以使用STL,当然STL会慢许多。 

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int MaxN = 500000 + 5, INF = 1000000015, MaxL = 25;
    
    int n, m, MSG;
    int A[MaxN], B[MaxN];
    
    char Str[MaxL];
    
     
    multiset<int> S, S2;
    multiset<int>::iterator It, It2;
    
    inline int gmax(int a, int b) {return a > b ? a : b;}
    inline int gmin(int a, int b) {return a < b ? a : b;}
    inline int Abs(int a) {return a < 0 ? -a : a;}
    
    void Before(int x) 
    {
    	It = S.lower_bound(x);
    	if (It == S.end()) 
    	{
    		It--;
    		MSG = gmin(MSG, x - *It);
    		return;
    	}
    	if (*It == x) 
    	{
    		MSG = 0;
    		return;
    	}
    	if (It == S.begin()) return;
    	It--;
    	MSG = gmin(MSG, x - *It);
    }
    
    void After(int x) 
    {
    	It = S.upper_bound(x);
    	if (It == S.end()) return;
    	MSG = gmin(MSG, *It - x);
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	S.clear(); S2.clear();
    	for (int i = 1; i <= n; ++i) 
    	{
    		scanf("%d", &A[i]);
    		B[i] = A[i];
    		S.insert(A[i]);
    	}
    	for (int i = 2; i <= n; ++i) 
    		S2.insert(Abs(A[i] - A[i - 1]));
    	MSG = INF;
    	for (int i = 1; i <= n; ++i) 
    	{
    		S.erase(S.find(A[i]));
    		Before(A[i]);
    		After(A[i]);
    		S.insert(A[i]);
    	}
    	int Pos, Num;
    	for (int i = 1; i <= m; ++i) 
    	{
    		scanf("%s", Str + 1);
    		if (Str[1] == 'I') 
    		{
    			scanf("%d%d", &Pos, &Num);
    			Before(Num);
    			After(Num);
    			S.insert(Num);
    			if (Pos == n) 
    			{
    				B[Pos] = Num;
    				continue;
    			}
    			S2.erase(S2.find(Abs(A[Pos + 1] - B[Pos])));
    			S2.insert(Abs(Num - B[Pos]));
    			S2.insert(Abs(A[Pos + 1] - Num));
    			B[Pos] = Num;
    		}
    		else if (Str[5] == 'G') 
    		{
    			It2 = S2.begin();
    			printf("%d
    ", *It2);
    		}
    		else 
    		{
    			printf("%d
    ", MSG);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    MYSQL 注射精华
    MySQL数据库安全配置
    linux命令
    python异常处理、反射、socket
    random、面向对象编程
    序列化、常用模块以及面向对象基础
    python 装饰器、递归原理、模块导入方式
    python递归、collections系列以及文件操作进阶
    python基础
    python简介
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4321317.html
Copyright © 2011-2022 走看看