題解 P1110 【[ZJOI2007]報表統計】
阿新 • • 發佈:2020-08-10
題目大意:
在最開始的時候,有一個長度為 \(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")