bz鏈結
洛谷鏈結
這道題真是喪心病狂。。。。
應該很容易就可以看出做法,但是寫**寫的.......
思路很簡單,用乙個平衡樹維護一下所有的操作就好了,重點講解一下**的細節
首先如果按照常規寫法的話,splay的節點要開到4000000,
直接炸飛,
由於任意時刻splay中的節點最多只有500000個,我們只需要開500000個節點就好了
然後將沒有用的節點**起來,下一次插入是插入到這些節點中
然後就是插入是將要插入的所有數字build成一顆平衡樹,直接接在要插入的位置,這樣會快很多
維護最大子段和與線段樹維護最大子段和方法一樣,維護以包含左端點且以左端點開頭的最大欄位和,以及以右端點結尾的最大欄位和
還有自身的最大子段和,然後就可以通過左右兒子的資訊快速算出當前節點的資訊了
具體細節可以看**
# include# include# include
# include
# include
# include
using
namespace
std;
const
int inf = 0xfffffff
;const
int mn = 500005
;int
n,m,a[mn];
struct
splay
void pushdown(int
x)
else
}if(rev[x])
}void rotate(int x,int &k)
son[y][tmp^1]=son[x][tmp],fa[son[y][tmp^1]]=y;
son[x][tmp]=y;
fa[y]=x,fa[x]=z;
updown(y),updown(x);
}void splay(int x,int &k)
rotate(x,k);}}
int find(int x,int
rk)
int split(int k,int
tot)
void recyc(int
x)
void
update()
void
rever()
}void build(int l,int r,int
f)
if(l1
,mid);
if(r>mid) build(mid+1
,r,mid);
v[now]=a[mid];
fa[now]=pre;
updown(now);
son[pre][(mid>=f)]=now;
}void
ins()
else id[i]=++cnt;
build(
1,tot,0);//
將要加入的數字建一顆splay
int z=id[(1+tot)>>1];//
取根int x=find(root,k+1),y=find(root,k+2
); splay(x,root),splay(y,son[x][
1]);
fa[z]=y;
son[y][
0]=z;
updown(y),updown(x);
}void
del()
void
query()
} t;
intmain()
return0;
}
BZOJ 1500, 維修數列
傳送門 編寫乙個支援插入 刪除 修改 翻轉 求和以及求和最大子串行的資料結構。splay無疑。但是寫太醜也是會tle的,比方說插入的時候應該以建樹的形式插入,而不是乙個點乙個點的形式。實現起來要注意的細節很多,對練習打splay挺有好處。陸陸續續除錯了好多天,總算在崩潰之前ac了 include c...
BZOJ 1500 維修數列
time limit 10 sec memory limit 64 mb submit 14433 solved 4701 submit status discuss 輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初...
bzoj 1500 維修數列
輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在 1 000,1 000 內。插入的數字總數不...