ZJOI2007报表统计·BZOJ1058
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1058
1058: [ZJOI2007]报表统计
Time Limit: 15 Sec Memory Limit: 162 MBDescription
小 Q的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一。经过仔细观察,小Q发现 统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。在最开始的时候,有一个长度为N的整数序列,并且有以下三种操作: INSERT i k 在原数列的第i个元素后面添加一个新元素k; 如果原数列的第i个元素已经添加了若干元素,则添加在这些元素的最后(见下面的例子) MIN_GAP 查询相邻两个元素的之间差值(绝对值)的最小值 MIN_SORT_GAP 查询所有元素中最接近的两个元素的差值(绝对值) 例如一开始的序列为 5 3 1 执行操作INSERT 2 9将得到: 5 3 9 1 此时MIN_GAP为2,MIN_SORT_GAP为2。 再执行操作INSERT 2 6将得到: 5 3 9 6 1 注意这个时候原序列的第2个元素后面已经添加了一个9,此时添加的6应加在9的后面。这个时候MIN_GAP为2,MIN_SORT_GAP为1。于是小 Q写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?
Input
第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。第二行为N个整数,为初始序列。接下来的M行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无多余空格或者空行)。
Output
对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。
Sample Input
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP
Sample Output
2
1
HINT
对于30%的数据,N ≤ 1000 , M ≤ 5000 对于100%的数据,N , M ≤500000 对于所有的数据,序列内的整数不超过5*108。
卧槽。。这题真TM恶心。。我从上午改到现在。。原因是TLE。。(妈蛋我要不是抱着试一试的心情交了这次我都不知道我特么AC了。。)在下面测,最慢的要2s多。。就不敢交
不过第一个版本的动态插入式的还是TLE。。优化的版本是直接Build树。。没什么好说的。。TTTTTTTTTTTTT________________TTTTTTTTTTTTT...
Codes:
1 #include<set> 2 #include<queue> 3 #include<vector> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 using namespace std; 10 const int N = 500010; 11 #define Sets(T,a,b,c){T[a].s[c] = b; T[b].p = a;} 12 #define rep(i,n) for(int i=1;i<=n;i++) 13 #define For(i,l,r) for(int i=l;i<=r;i++) 14 15 struct tnode{ 16 int s[2],v,p,num; 17 }T1[N<<1],T2[N<<1]; 18 19 int kth,val,A[N],Last[N],MSG=2147483647,n,m; 20 int cnt,root1,root2,tot1,tot2,y,z; 21 22 int read(){ 23 int num = 0; char ch = getchar(); 24 int q = 0; 25 while(ch<'0'||ch>'9') { 26 if(ch=='-') q = 1; 27 ch = getchar(); 28 } 29 while(ch>='0'&&ch<='9'){ 30 num = num * 10 + ch-'0'; 31 ch = getchar(); 32 } 33 return (q==1)?(-num):num; 34 } 35 36 void Rot(tnode T[],int x){ 37 //cnt++; 38 int y = T[x].p , z = T[y].p; 39 int lx = T[y].s[1] == x , ly = T[z].s[1] == y; 40 Sets(T,y,T[x].s[!lx],lx); 41 Sets(T,z,x,ly); 42 Sets(T,x,y,lx^1); 43 } 44 45 void Splay(tnode T[],int i,int goal,int &root){ 46 while(T[i].p!=goal){ 47 if(T[T[i].p].p!=goal) Rot(T,T[i].p); 48 Rot(T,i); 49 } 50 if(!goal) root = i; 51 } 52 53 void Insert_1(int V,int i){ 54 if(!i){ 55 root1 = ++tot1;T1[root1].num = 1;T1[root1].p = 0;T1[root1].v = V; 56 return; 57 } 58 MSG = min(MSG,abs(V-T1[i].v)); 59 if(T1[i].v==V) T1[i].num++; 60 else{ 61 if(!T1[i].s[V>T1[i].v]){ 62 T1[i].s[V>T1[i].v] = ++tot1;T1[tot1].p = i;T1[tot1].v = V; T1[tot1].num = 1; 63 Splay(T1,tot1,0,root1); 64 } 65 else Insert_1(V,T1[i].s[V>T1[i].v]); 66 } 67 } 68 69 void Insert_2(int V,int i){ 70 if(!i){ 71 root2 = ++tot2;T2[root2].num = 1;T2[root2].p = 0;T2[root2].v = V; 72 return; 73 } 74 if(T2[i].v==V) T2[i].num++; 75 else{ 76 if(!T2[i].s[V>T2[i].v]){ 77 T2[i].s[V>T2[i].v] = ++tot2;T2[tot2].p = i;T2[tot2].v = V; T2[tot2].num = 1; 78 Splay(T2,tot2,0,root2); 79 } 80 else Insert_2(V,T2[i].s[V>T2[i].v]); 81 } 82 } 83 84 int prev(int i){ 85 int Next = T2[i].s[0]; 86 while(T2[Next].s[1]) Next = T2[Next].s[1]; 87 return Next; 88 } 89 90 void Delete(int i){ 91 if(T2[i].num>1) { 92 T2[i].num--; 93 return; 94 } 95 Splay(T2,i,0,root2); 96 if(T2[i].s[0]){ 97 Splay(T2,prev(i),i,root2); 98 Sets(T2,T2[i].s[0],T2[i].s[1],1); 99 T2[T2[i].s[0]].p = 0; 100 root2 = T2[i].s[0]; 101 }else{ 102 if(T2[i].s[1]){root2 = T2[i].s[1];T2[T2[i].s[1]].p = 0;} 103 else root2 = 0; 104 } 105 T2[i].num = T2[i].p = T2[i].s[0] = T2[i].s[1] = T2[i].v = 0; 106 } 107 108 int Min(int root2){ 109 int Next = T2[root2].s[0]; 110 if(!Next) return T2[root2].v; 111 while(T2[Next].s[0]) Next =T2[Next].s[0]; 112 return T2[Next].v; 113 } 114 115 int find(int V,int i){ 116 if(V==T2[i].v) return i; 117 else return find(V,T2[i].s[V>T2[i].v]); 118 } 119 120 void Build1(int l,int r,int &i,int p){ 121 if(l>r) return; 122 int m = (l+r) >> 1; 123 T1[i=++tot1].p = p; T1[i].v = A[m]; T1[i].num++; 124 Build1(l,m-1,T1[i].s[0],i); 125 Build1(m+1,r,T1[i].s[1],i); 126 } 127 128 void Build2(int l,int r,int &i,int p){ 129 if(l>r) return; 130 int m = (l+r) >> 1; 131 T2[i=++tot2].p = p; T2[i].v = Last[m];T2[i].num++; 132 Build2(l,m-1,T2[i].s[0],i); 133 Build2(m+1,r,T2[i].s[1],i); 134 } 135 136 int main(){ 137 //freopen("form.in","r",stdin); 138 //freopen("form.out","w",stdout); 139 n = read(); m = read(); 140 rep(i,n){ 141 A[i] = read(); 142 //Insert_1(A[i],root1); 143 // if(i>1) Insert_2(abs(A[i]-A[i-1]),root2); 144 //Last[i] = A[i]; 145 if(i>1) Last[i-1] = abs(A[i] - A[i-1]); 146 } 147 sort(Last+1,Last+n); 148 Build2(1,n-1,root2,0); 149 rep(i,n) Last[i] = A[i]; 150 sort(A+1,A+n+1);For(i,1,n-1) MSG=min(MSG,abs(A[i]-A[i+1])); 151 Build1(1,n,root1,0); 152 rep(i,n) A[i] = Last[i]; 153 char op[20];int troot; 154 rep(i,m){ 155 scanf("%s",&op); 156 if(op[0]=='I'){ 157 kth = read() , val = read(); 158 if(kth<n) { 159 troot = find(abs(Last[kth]-A[kth+1]),root2); 160 Delete(troot); 161 } 162 Insert_2(abs(val-Last[kth]),root2); 163 if(kth<n) Insert_2(abs(val-A[kth+1]),root2); 164 Insert_1(val,root1); 165 Last[kth] = val; 166 continue; 167 } 168 if(op[4]=='S') printf("%d\n",MSG); 169 if(op[4]=='G') printf("%d\n",Min(root2)); 170 } 171 //printf("%d\n",cnt); 172 return 0; 173 }
好长。。T___T。。好像还没说做法,我sb地建了两棵平衡树。。一棵维护MIN_GAP 一棵维护MIN_SORT_GAP。。
实际上,可以用堆维护MIN_GAP。。或者是Set。。