bzoj 1058: [ZJOI2007]報表統計【set】
阿新 • • 發佈:2018-12-05
我想寫FHQtreap的!是set自己跑進程式碼的!因為太好寫了
是有點慢……洛谷上不吸氧會T一個點
就是,用一個set p維護所有點值,ans維護MIN_SORT_GAP的答案,每次insert一個點的時候都查一下它在p裡的前驅後繼,更新一下ans即可;用一個multiset c維護差分後的序列,a[i]表示第i個位置的開頭數字,b[i]表示結尾數字,每次在x位置新插入值v的時候都要c.erase(c.find(abs(a[x+1]-b[x]))),c.insert(abs(a[x+1]-v)),c.insert(abs(v-b[x]))(這個應該很好理解)然後查詢的時候直接找begin即可
差分的時候注意一下邊界
想要快的話大概是線段樹+樹上二分代替p,平衡樹代替set?
#include<iostream> #include<cstdio> #include<set> #include<algorithm> using namespace std; const int N=500005; int n,m,a[N],b[N],ans=1e9; char o[20]; set<int>p; multiset<int>c; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=b[i]=read(); if(i>1) { c.insert(abs(a[i]-a[i-1])); set<int>::iterator it=p.lower_bound(a[i]); if(it!=p.end()) ans=min(ans,(*it)-a[i]);//,cerr<<a[i]<<" "<<*it<<endl; if(it!=p.begin()) ans=min(ans,a[i]-(*--it)); } p.insert(a[i]); } while(m--) { scanf("%s",o+1); if(o[1]=='I') { int x=read(),v=read(); set<int>::iterator it=p.lower_bound(v); if(it!=p.end()) ans=min(ans,(*it)-v); if(it!=p.begin()) ans=min(ans,v-(*--it)); p.insert(v); if(x<n) c.erase(c.find(abs(a[x+1]-b[x]))),c.insert(abs(a[x+1]-v)); c.insert(abs(v-b[x])); b[x]=v; } else if(o[5]=='G') printf("%d\n",*c.begin()); else printf("%d\n",ans); } return 0; }