題目傳送門
題目大意:給一棵樹,若干種操作:路徑加,路徑乘,刪邊加邊,求路徑和。
看到刪邊加邊就知道是 lct
lctlc
t 了。
路徑加路徑乘都是打個標記的事,但是在更新 sum
sumsu
m 的時候,sum
sumsu
m 不僅要乘上乘法標記,還要加上加法標記乘 siz
esize
size
的積。(siz
esize
size
是子樹大小)
以及這題的模數的平方剛好爆 int
intin
t,所以要開 lon
glon
glong~long
longlo
ng。以及我長時間 wa 5分的原因可能是比較稀有的……
眾所周知,laz
ylazy
lazy
標記有兩種寫法,第一種在得到 laz
ylazy
lazy
標記時更新自己的 val
ue
value
valu
e 以及 sum
sumsu
m,然後在 pus
hdow
npushdown
pushdo
wn的時候更新兒子的 val
ue
value
valu
e 和 sum
sumsu
m;第二種是得到 laz
ylazy
lazy
標記的時候不更新,在 pus
hdow
npushdown
pushdo
wn的時候更新自己的 val
ue
value
valu
e 和 sum
sumsu
m。對於線段樹而言,這兩種寫法是等價的,但是對於 spl
ay
splay
spla
y 而言,第二種寫法卻是錯的。因為 rot
at
erotate
rotate
操作裡面,旋轉完之後父親變成了我的兒子,要 upd
ate(
fa
)update(fa)
update
(fa)
然後 upd
ate(
x)
update(x)
update
(x),如果用第二種寫法的話就會錯,原因想想就能明白。
**如下:
#include
#include
#include
using
namespace std;
#define maxn 100010
#define mod 51061
#define ll long long
struct node
void
update
(ll plus,ll times)
void
pushdown()
}void
check()
bool
notroot()
};node *root[maxn]
;node *zhan[maxn]
;int t=0;
void
rotate
(node *x)
else
fa->fa=x;x-
>fa=gfa;
if(gfa!=
null
&&gfa-
>zuo==fa)gfa-
>zuo=x;
if(gfa!=
null
&&gfa-
>you==fa)gfa-
>you=x;
fa->
check()
;x->
check()
;}#define witch(x) (x->fa->zuo==x)
void
splay
(node *x)
}void
access
(node *x)
void
makeroot
(node *x)
void
split
(node *x,node *y)
void
link
(node *x,node *y)
void
del(node *x,node *y)
int n,m;
intmain()
if(s[0]
=='-')if
(s[0]==
'*')
if(s[0]
=='/')}
}
國家集訓隊 Tree II
題目 這不是線段樹模板2放 lct 上了嗎 於是開始碼碼碼 之後一直wawawa 於是開始調調調 之後旁邊的慎老師看了一看 就說,你下放乘法標記的時候不乘加法標記嗎 我 include include include include define maxn 300005 define re regi...
國家集訓隊 Tree II
lct維護這種東西是要比線段樹要噁心的多的 畢竟線段樹的區間大小是可以直接通過區間左右端點算出的,但是lct就不行,必須手動維護。並且,線段樹的維護是 左兒子 右兒子 但是lct的維護是 左兒子 自己 右兒子 請務必先把線段樹模板做掉,關於運算的優先順序什麼的實在不應該放到這道題裡講吧 注意細節,比...
Luogu1501 國家集訓隊 Tree II
題目描述 一棵n個點的樹,每個點的初始權值為1。對於這棵樹有q個操作,每個操作為以下四種操作之一 u v c 將u到v的路徑上的點的權值都加上自然數c u1 v1 u2 v2 將樹中原有的邊 u1,v1 刪除,加入一條新邊 u2,v2 保證操作完之後仍然是一棵樹 u v c 將u到v的路徑上的點的權...