bzoj 1058 [ZJOI2007]报表统计(set)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1058 [ZJOI2007]报表统计(set)相关的知识,希望对你有一定的参考价值。
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1058
【题意】
一个序列,提供插入,查询相邻最小差值,查询任意最小差值的操作。
【思路】
Set
用两个set,listed装所有的相邻差值,sorted装所有的数。然后用front[x],last[x]记录位置x上开始和结束的数。
对于Insert,维护listed:删除front[x+1]与last[x]的差值并插入两个新的差值,插入sorted后与前一个后一个作差更新答案。
【代码】
1 #include<cmath> 2 #include<set> 3 #include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #define ite multiset<int>::iterator 7 using namespace std; 8 9 typedef long long ll; 10 const int N = 3e6+10; 11 12 multiset<int> sorted,listed; 13 14 int n,m,tomin; 15 int last[N],front[N]; 16 17 ll read() { 18 char c=getchar(); 19 ll f=1,x=0; 20 while(!isdigit(c)) { 21 if(c==‘-‘) f=-1; c=getchar(); 22 } 23 while(isdigit(c)) 24 x=x*10+c-‘0‘,c=getchar(); 25 return x*f; 26 } 27 int abs(int x) { return x<0? -x:x; } 28 29 int main() 30 { 31 n=read(); m=read(); 32 tomin=1e9; 33 for(int i=1;i<=n;i++) { 34 front[i]=read(); 35 last[i]=front[i]; 36 sorted.insert(front[i]); 37 if(i!=1) listed.insert(abs(front[i]-front[i-1])); 38 } 39 ite l; 40 for(ite r=sorted.begin();r!=sorted.end();r++) { 41 if(r!=sorted.begin()) 42 tomin=min(tomin,abs(*r-*l)); 43 l=r; 44 } 45 char op[20]; int x,y; 46 while(m--) { 47 scanf("%s",op); 48 if(op[0]==‘I‘) { 49 x=read(),y=read(); 50 ite it=sorted.insert(y); 51 if(it!=sorted.begin()) 52 --it , tomin=min(tomin,abs(y-*it)) , ++it; 53 if(it!=sorted.end()) 54 ++it , tomin=min(tomin,abs(*it-y)) , --it; 55 it=listed.find(abs(front[x+1]-last[x])); 56 listed.erase(it); 57 listed.insert(abs(y-front[x+1])); 58 listed.insert(abs(y-last[x])); 59 last[x]=y; 60 } else 61 if(strlen(op)==7) { 62 printf("%d\n",*listed.begin()); 63 } else { 64 printf("%d\n",tomin); 65 } 66 } 67 return 0; 68 }
以上是关于bzoj 1058 [ZJOI2007]报表统计(set)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj P1058 [ZJOI2007]报表统计——solution