BZOJ1058 [ZJOI2007]报表统计 set
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1058.html
题目传送门 - BZOJ1058
题解
考虑用两个 multiset 分别维护两个答案。
一个直接按照权值维护,另一个维护一下相邻位置的差。
比较容易想到如何维护的吧,不多讲,看代码吧。
代码
#include <bits/stdc++.h> using namespace std; const int N=500005; int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)&&ch!='-') ch=getchar(); if (ch=='-') f=-1,ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*f; } int n,m; vector <int> v[N]; multiset <int> S1,S2; int ans1; int add1(int x){ S1.insert(x); multiset <int> :: iterator p=S1.find(x); multiset <int> :: iterator L=p,R=p; --L,++R; ans1=min(ans1,min(abs((*p)-(*L)),abs((*p)-(*R)))); } int main(){ n=read(),m=read(); S1.clear(); S2.clear(); S1.insert(-2e9); S1.insert(ans1=2e9); for (int i=1;i<=n;i++){ int x=read(); v[i].clear(); v[i].push_back(x); add1(x); if (i>1) S2.insert(abs(v[i][0]-v[i-1][0])); } v[n+1].clear(); v[n+1].push_back(2e9); S2.insert(abs(v[n+1][0]-v[n][0])); while (m--){ char ch[40]; int a,b; scanf("%s",ch); if (ch[0]=='I'){ a=read(),b=read(); add1(b); int k=(int)v[a].size(); S2.erase(S2.find(abs(v[a][k-1]-v[a+1][0]))); S2.insert(abs(v[a][k-1]-b)); v[a].push_back(b); S2.insert(abs(b-v[a+1][0])); } else if (ch[4]=='G'){ printf("%d\n",*S2.begin()); } else if (ch[4]=='S'){ printf("%d\n",ans1); } } return 0; }