Warriors_Cat @ 2020-03-25 20:23:19
请问一下,这道题以下代码为什么 TLE 70 分?
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
const int INF = 0x7fffffff;
int anss, lst, m, n, opt, x, num, Root, ch[1100010][2], cnt[1100010], siz[1100010], pri[1100010], val[1100010];
inline int new_node(int x){
val[++num] = x;
pri[num] = rand();
cnt[num] = siz[num] = 1;
return num;
}
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
inline void upd(int x){
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
return;
}
inline void Rotate(int &x, int id){
int y = ch[x][id ^ 1];
ch[x][id ^ 1] = ch[y][id];
ch[y][id] = x;
x = y;
upd(ch[x][id]); upd(x);
return;
}
inline void Insert(int &x, int key){
if(!x){
x = new_node(key);
return;
}
if(key == val[x]) cnt[x]++;
else{
int id = key < val[x] ? 0 : 1;
Insert(ch[x][id], key);
if(pri[x] < pri[ch[x][id]]) Rotate(x, id ^ 1);
}
upd(x);
return;
}
inline void Delete(int &x, int key){
if(!x) return;
if(key == val[x]){
if(cnt[x] > 1){
cnt[x]--;
upd(x);
return;
}
if(ch[x][0] || ch[x][1]){
if(!ch[x][1] && pri[ch[x][0]] > pri[ch[x][1]]){
Rotate(x, 1);
Delete(ch[x][1], key);
}
else{
Rotate(x, 0);
Delete(ch[x][0], key);
}
upd(x);
}
else x = 0;
return;
}
if(key < val[x]) Delete(ch[x][0], key);
else Delete(ch[x][1], key);
upd(x);
return;
}
inline int Pre(int key){
int x = Root, ans = -INF;
while(x){
if(val[x] < key) ans = val[x], x = ch[x][1];
else x = ch[x][0];
}
return ans;
}
inline int Suf(int key){
int x = Root, ans = INF;
while(x){
if(val[x] > key) ans = val[x], x = ch[x][0];
else x = ch[x][1];
}
return ans;
}
inline int Find(int x, int key){
if(!x) return 0;
if(key == val[x]) return siz[ch[x][0]] + 1;
else if(key < val[x]) return Find(ch[x][0], key);
else return siz[ch[x][0]] + cnt[x] + Find(ch[x][1], key);
}
inline int Rank(int x, int k){
if(!x) return INF;
if(k <= siz[ch[x][0]]) return Rank(ch[x][0], k);
else if(k <= siz[ch[x][0]] + cnt[x]) return val[x];
else return Rank(ch[x][1], k - siz[ch[x][0]] - cnt[x]);
}
int main(){
Root = new_node(-INF), ch[Root][1] = new_node(INF);
upd(Root);
n = read(); m = read();
for(register int i = 1; i <= n; ++i){
x = read();
Insert(Root, x);
}
for(register int i = 1; i <= m; ++i){
opt = read(); x = read();
x ^= lst;
if(opt == 1) Insert(Root, x);
if(opt == 2) Delete(Root, x);
if(opt == 3) Insert(Root, x), lst = Find(Root, x) - 1, anss ^= lst, Delete(Root, x);
if(opt == 4) lst = Rank(Root, x + 1), anss ^= lst;
if(opt == 5) Insert(Root, x), lst = Pre(x), anss ^= lst, Delete(Root, x);
if(opt == 6) Insert(Root, x), lst = Suf(x), anss ^= lst, Delete(Root, x);
}
printf("%d", anss);
return 0;
}
自认为常数已经够优了,或者说是我的写法有问题?
by Smile_Cindy @ 2020-03-25 20:29:47
@fhh_orz 有些人的平衡树代码实现必须保证数x在序列里出现过。
by IntrepidStrayer @ 2020-03-25 20:30:57
原来是这样@Alpha
by Smile_Cindy @ 2020-03-25 20:31:23
@蒟蒻的名字 Splay的精细实现,仅供借鉴
因为我并不会Treap
void find(int x)
{
int cur=rt;
if(!cur)return;
while(T[cur].ch[x>T[cur].val] && T[cur].val!=x)cur=T[cur].ch[x>T[cur].val];
splay(cur);
}
int prev(int x)
{
find(x);
int cur=rt;
if(T[cur].val<x)return cur;
cur=T[cur].ch[0];
while(T[cur].ch[1])cur=T[cur].ch[1];
splay(cur);
return cur;
}
int next(int x)
{
find(x);
int cur=rt;
if(T[cur].val>x)return cur;
cur=T[cur].ch[1];
while(T[cur].ch[0])cur=T[cur].ch[0];
splay(cur);
return cur;
}
int rank(int x)
{
find(x);
if(T[rt].val<x)return T[T[rt].ch[0]].siz+T[rt].cnt;
else return T[T[rt].ch[0]].siz;
}
by LJB00131 @ 2020-03-25 20:35:33
所以这件事情教导我们fhq treap还是很香的
by IntrepidStrayer @ 2020-03-25 20:40:38
为什么我写的treap不需要x在树中啊