• luogu1110 报表统计


    [ZJOI2007] 报表统计

    题目描述

    小 Q 的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小 Q 希望可以帮妈妈分担一些工作,作为她的生日礼物之一。

    经过仔细观察,小 Q 发现统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。

    在最开始的时候,有一个长度为 \(n\) 的整数序列 \(a\),并且有以下三种操作:

    • INSERT i k:在原数列的第 \(i\) 个元素后面添加一个新元素 \(k\);如果原数列的第 \(i\) 个元素已经添加了若干元素,则添加在这些元素的最后(见样例说明)。
    • MIN_GAP:查询相邻两个元素的之间差值(绝对值)的最小值。
    • MIN_SORT_GAP:查询所有元素中最接近的两个元素的差值(绝对值)。

    于是小 Q 写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

    输入格式

    第一行包含两个整数,分别表示原数列的长度 \(n\) 以及操作的次数 \(m\)

    第二行为 \(n\) 个整数,为初始序列,第 \(i\) 个整数表示 \(a_i\)

    接下来的 \(m\) 行,每行一个操作,即INSERT i kMIN_GAPMIN_SORT_GAP 中的一种(无多余空格或者空行)。

    输出格式

    对于每一个 MIN_GAPMIN_SORT_GAP 命令,输出一行答案即可。

    样例 #1

    样例输入 #1

    3 5
    5 3 1
    INSERT 2 9
    MIN_SORT_GAP
    INSERT 2 6
    MIN_GAP
    MIN_SORT_GAP
    

    样例输出 #1

    2
    2
    1
    

    提示

    样例输入输出 1 解释

    一开始的序列为 \(\{5,3,1\}\)

    执行操作 INSERT 2 9 将得到 \(\{5,3,9,1\}\),此时 MIN_GAP\(2\)MIN_SORT_GAP\(2\)

    再执行操作 INSERT 2 6 将得到:\(\{5,3, 9, 6, 1\}\)

    注意这个时候原序列的第 \(2\) 个元素后面已经添加了一个 \(9\),此时添加的 \(6\) 应加在 \(9\) 的后面。这个时候 MIN_GAP\(2\)MIN_SORT_GAP\(1\)


    数据规模与约定

    对于全部的测试点,保证 \(2 \le n, m \le 5\times10^5\)\(1 \leq i \leq n\)\(0 \leq a_i, k \leq 5 \times 10^8\)


    首先,题目要细读。题意是在n个位置放上n个数,后面会在某个位置再在后面加数。这时就相当于把多个数分为n段,段所段之间是有序的,段内各个数之间也是有序的。
    两种询问,一种是不管分段和次序,所有的数的最小跨度。另一种是相临两个数之间的最小跨度。
    第一种跨度明显用平衡树维护,每次求前驱和后继,这样就有了最小跨度。
    第二种用可删除堆,也就是两个堆,来维护。
    平衡树太难写了,于是就写了一个multiset。学了不少东西。


    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5e6+10;
    multiset<int>t;//维护排序最小值 
    struct Heap
    {
    	priority_queue< int,vector <int> , greater<int> >qr,qc;
    	void insert(int x)
    	{
    		qr.push(x);
    	}
    	void del(int x)
    	{
    		qc.push(x);
    	}
    	int get()
    	{
    		while(!qc.empty()&&!qr.empty()&&qr.top()==qc.top())qr.pop(),qc.pop();
    		return qr.top();
    	}
    }heap;//维护相邻最小值 
    int n,m;
    char s[20];
    int sz[maxn][2];
    int mn=0x7fffffff,smn=0x7fffffff;
    typedef multiset<int>::iterator it;
    int abs(int x){return x<0?-x:x;}
    it tp;
    void print()
    {
    	cout<<"********************"<<endl;
    	for(it x=t.begin();x!=t.end();++x)cout<<*x<<endl;
    	cout<<"********************"<<endl;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	memset(sz,-1,sizeof sz);
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%d",&sz[i][0]);
    		if(i!=1)heap.insert(abs(sz[i][0]-sz[i-1][0]));
    		if(smn)
    		{
    			pair<it,it> pt=t.equal_range(sz[i][0]);
    			if(pt.first != pt.second){smn=0;continue;}
    			if(pt.second !=t.end())smn=min(smn,abs(*pt.second-sz[i][0]));
    			if(pt.first !=t.begin())tp=pt.first,tp--,smn=min(smn,abs(sz[i][0]-*(tp)));
    			t.insert(sz[i][0]);
    		}
    	}
    	while(m--)
    	{
    		scanf("%s",s);
    		if(s[4]=='S')printf("%d\n",smn);
    		else if (s[4]=='G')printf("%d\n",heap.get());
    		else
    		{
    			int pos,val;
    			scanf("%d%d",&pos,&val);
    			if(sz[pos][1]==-1)heap.insert(abs(sz[pos][0]-val));
    			else heap.insert(abs(sz[pos][1]-val));
    			if(pos!=n)heap.insert(abs(sz[pos+1][0]-val)),heap.del(abs(sz[pos+1][0]-sz[pos][sz[pos][1]==-1?0:1]));
    			sz[pos][1]=val;
    			if(smn)
    			{
    				pair<it,it> pt=t.equal_range(val);
    				if(pt.first != pt.second){smn=0;continue;}
    				if(pt.second !=t.end())smn=min(smn,abs(*pt.second-val));
    				if(pt.first!=t.begin())tp=pt.first,tp--,smn=min(smn,abs(val-*(tp)));
    				t.insert(val);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    [LeetCode] 617. Merge Two Binary Trees
    [LeetCode] 738. Monotone Increasing Digits
    289. Game of Life
    305. Number of Islands II
    288. Unique Word Abbreviation
    271. Encode and Decode Strings
    393. UTF-8 Validation
    317. Shortest Distance from All Buildings
    286. Walls and Gates
    296. Best Meeting Point
  • 原文地址:https://www.cnblogs.com/gryzy/p/16521643.html
Copyright © 2020-2023  润新知