傳送門:
time limit: 15 sec memory limit: 162 mb
小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寫了乙個程式,使得程式可以自動完成這些操作,但是他發現對於一些大的報表他的程式執行得很慢,你能幫助他改進程式麼?
第一行包含兩個整數n,m,分別表示原數列的長度以及操作的次數。第二行為n個整數,為初始序列。接下來的m行每行乙個操作,即「insert i k」,「min_gap」,「min_sort_gap」中的一種(無多餘空格或者空行)。
對於每乙個「min_gap」和「min_sort_gap」命令,輸出一行答案即可。
3 55 3 1
insert 2 9
min_sort_gap
insert 2 6
min_gap
min_sort_gap22
1對於30%的資料,n ≤ 1000 , m ≤ 5000 對於100%的資料,n , m ≤500000 對於所有的資料,序列內的整數不超過5*108。
臥槽。。這題真tm噁心。。我從上午改到現在。。原因是tle。。(媽蛋我要不是抱著試一試的心情交了這次我都不知道我特麼ac了。。)在下面測,最慢的要2s多。。就不敢交
不過第乙個版本的動態插入式的還是tle。。優化的版本是直接build樹。。沒什麼好說的。。ttttttttttttt________________ttttttttttttt...
codes:
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9
using
namespace
std;
10const
int n = 500010;11
#define sets(t,a,b,c)
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++)
1415
struct
tnodet1[n<<1],t2[n<<1
];18
19int kth,val,a[n],last[n],msg=2147483647
,n,m;
20int
cnt,root1,root2,tot1,tot2,y,z;
2122
intread()
29while(ch>='
0'&&ch<='9'
)33return (q==1)?(-num):num;34}
3536
void rot(tnode t,int
x)44
45void splay(tnode t,int i,int goal,int &root)
50if(!goal) root =i;51}
5253
void insert_1(int v,int
i)58 msg = min(msg,abs(v-t1[i].v));
59if(t1[i].v==v) t1[i].num++;
60else
65else insert_1(v,t1[i].s[v>t1[i].v]);66}
67}6869
void insert_2(int v,int
i)74
if(t2[i].v==v) t2[i].num++;
75else
80else insert_2(v,t2[i].s[v>t2[i].v]);81}
82}8384
int prev(int
i)89
90void delete(int
i)95 splay(t2,i,0
,root2);
96if(t2[i].s[0
])else
103else root2 = 0
;104
}105 t2[i].num = t2[i].p = t2[i].s[0] = t2[i].s[1] = t2[i].v = 0
;106
}107
108int min(int
root2)
114115
int find(int v,int
i)119
120void build1(int l,int r,int &i,int
p)127
128void build2(int l,int r,int &i,int
p)135
136int
main()
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];
153char op[20];int
troot;
154rep(i,m)
162 insert_2(abs(val-last[kth]),root2);
163if(kth1
]),root2);
164insert_1(val,root1);
165 last[kth] =val;
166continue
;167
}168
if(op[4]=='
s') printf("
%d\n
",msg);
169if(op[4]=='
g') printf("
%d\n
",min(root2));
170}
171//
printf("%d\n",cnt);
172return0;
173 }
好長。。t___t。。好像還沒說做法,我sb地建了兩棵平衡樹。。一棵維護min_gap 一棵維護min_sort_gap。。
實際上,可以用堆維護min_gap。。或者是set。。
ZJOI2007 報表統計
不想描述了,心累。兩個操作分別用splay和線段樹來維護 全域性的差值最小直接用splay在插入的時候維護前驅後繼即可 相鄰最小差值我們可以這樣搞 首先 用線段樹維護相鄰的最小值 可以注意到插入元素的操作,如果是在乙個元素之後反覆插入,這些元素之間更新出來的最小值是不會發生改變的。只有元素與元素之間...
ZJOI2007 報表統計
在原數列第 i 個後面新增乙個新元素 k 如果原數列的第 i 個元素已經新增了若干元素,則新增在這些元素的最後。查詢相鄰兩個元素的差值的絕對值的最小值。查詢所有元素中一對元素的差值的絕對值的最小值。第乙個操作很好維護,若要在第 i 個元素後面插值,那麼實際需要插入的位置是 i s i 1 其中 s ...
ZJOI2007 報表統計
題解 一道不錯的模板題 對於第乙個詢問,只需維護乙個支援刪除的堆 方法1.再維護乙個堆,將刪除的數加入這個堆,每次取元素時判斷一下是否和另乙個堆相等 方法2.利用左偏樹可以刪除任意節點 太久不寫都忘了 當然也可以維護一顆平衡樹 對於第二個詢問,只需弄一顆平衡樹求它的前驅後繼就可以了 include ...