AmazingCounters.com

ZJOI2007报表统计·BZOJ1058

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1058

 

 

1058: [ZJOI2007]报表统计

Time Limit: 15 Sec  Memory Limit: 162 MB

Description

小 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

3 5
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP

Sample Output

2
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。。

posted @ 2014-07-22 20:03  ZJDx1998  阅读(358)  评论(0编辑  收藏  举报