P1110 [ZJOI2007]报表统计

题目大意:

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

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

题解:

这道题我们可以将两种询问分开考虑。

首先是第一种询问,我们可以用 \(pair\)\(map\) 来映射插入的位置和对应的值,第一个关键词表示塞到哪个元素的后面,第二个关键词表示是插入的第几个元素。这样每插入一个元素,我们考虑删除这个元素前驱后继的相邻差值,再加入这个元素与前驱和后继的差值,这个东西可以用 \(set\) 来维护。

然后第二种询问就比较的简单,他的值是单调递减的, 所以我们只需要在插入一个值之后找到他的前驱和后继,在取差值更新答案即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+5;
int n,q;
int a[N],cnt[N];
string opt;
int x,y;
map<pair<int,int>,int> mp;
set<pair<int,int> > st1;
set<int> st2;
multiset<int> minn;
int ans=1e9+7;
signed main()
{
	scanf("%lld%lld",&n,&q);
	for(int i=1;i<=n;++i)
	scanf("%lld",&a[i]);
	for(int i=1;i<=n;++i)
	{
		pair<int,int> tmp=make_pair(i,++cnt[i]);
		mp[tmp]=a[i];
		st1.insert(tmp);
		st2.insert(a[i]);
	}
	for(set<pair<int,int> >::iterator i=st1.begin(),j;i!=st1.end();j=i,++i)
	{
		if(i==st1.begin())
		continue;
		minn.insert(abs(mp[*j]-mp[*i]));
	}
	mp[make_pair(n+1,1)]=1e18+7;
	st1.insert(make_pair(n+1,1));
	for(set<int>::iterator i=st2.begin(),j;i!=st2.end();j=i,++i)
	{
		if(i==st2.begin())
		continue;
		ans=min(ans,abs(*j-*i));
	}
	st2.insert(-1e18-7);
	st2.insert(1e18+7);
	for(int i=1;i<=q;++i)
	{
		cin>>opt;
		if(opt=="INSERT")
		{
			scanf("%lld%lld",&x,&y);
			pair<int,int> tmp=make_pair(x,++cnt[x]);
			mp[tmp]=y;
			set<pair<int,int> >::iterator pre=st1.find(make_pair(x,cnt[x]-1));
			set<pair<int,int> >::iterator nxt=st1.find(make_pair(x+1,1));
			st1.insert(tmp);
			minn.erase(minn.find(abs(mp[*pre]-mp[*nxt])));
			minn.insert(abs(y-mp[*pre]));
			minn.insert(abs(y-mp[*nxt]));
			set<int>::iterator bef=st2.upper_bound(y);
			--bef;
			set<int>::iterator  aft=st2.lower_bound(y);
			st2.insert(y);
			ans=min(ans,min(abs(y-*bef),abs(y-*aft)));
		}
		if(opt=="MIN_GAP")
		printf("%lld\n",*minn.begin());
		if(opt=="MIN_SORT_GAP")
		printf("%lld\n",ans);
	}
	return 0;
}

但是啊,如果有小可爱尝试了一下这个代码会发现他 \(TLE\) 到死去活来,所以说,火车头他不香吗?

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
posted @ 2020-08-10 14:40  Point_King  阅读(134)  评论(0编辑  收藏  举报