(建议您从上方链接进入我的个人网站查看此 Blog,在 Luogu 中图片会被墙掉,部分 Markdown 也会失效)
rt,树剖比较简单就不具体写做法了,总之就是之前实现的一个及其阴间的指针版树剖模板,然后一直 RE 没调出来,今天想着重调一下,结果看了一遍就找到问题了,判断深度时直接判断了节点的深度而非节点所在链顶的深度。
该说不说这玩意拿指针是真难写,正常的树剖默认下标为
xxxxxxxxxx190123
456789
10using namespace std;11
12mt19937 rnd(random_device{}());13int rndd(int l, int r){return rnd() % (r - l + 1) + l;}14
15typedef unsigned int uint;16typedef unsigned long long unll;17typedef long long ll;18
19struct Node;20
21struct Edge{22 Edge* nxt;23 Node* to;24 void* operator new(size_t);25 Edge(Edge* nxt, Node* to):nxt(nxt), to(to){;}26 Edge(void) = default;27}eData[210000];28void* Edge::operator new(size_t){static Edge* P = eData; return ++P;}29int N, M, R, MOD;30
31struct Node{32 33 int val;34 int dfn;35 int dep;36 int siz;37 Node* fa;38 Node* top;39 Node* hson;40 Edge* head;41 Node(int val):val(val){;}42 Node(void) = default;43 void* operator new(size_t);44}nData[110000];45void* Node::operator new(size_t){static Node* P = nData; return ++P;}46Node* tr[110000];47Node* idx[110000];48
49template<typename T = int>50inline T read(void);51
52void dfs_pretreat(Node* p, Node* fa){53 p->fa = fa;54 p->dep = dep(p->fa) + 1;55 p->siz = 1;56 for(auto i = p->head; i; i = i->nxt){57 if(SON == fa)continue;58 // printf("%d %d\n", SON->val, fa ? fa->val : 0);59 dfs_pretreat(SON, p);60 p->siz += SON->siz;61 if(siz(SON) > siz(p->hson))p->hson = SON;62 }63}64void dfs_build(Node* p, Node* top){65 static int dfn(0);66 p->dfn = ++dfn;67 idx[p->dfn] = p;68 p->top = top;69 if(p->hson)dfs_build(p->hson, top);70 for(auto i = p->head; i; i = i->nxt){71 if(SON != p->hson && SON != p->fa){72 dfs_build(SON, SON);73 }74 }75}76class SegTree{77private:78 ll st[110000 << 2], lt[110000 << 2];79 80 81 82 83 84 85public:86 void Pushdown(int p, int gl, int gr){87 st[LS] = (st[LS] + SIZL * lt[p] % MOD) % MOD,88 st[RS] = (st[RS] + SIZR * lt[p] % MOD) % MOD,89 lt[LS] = (lt[LS] + lt[p]) % MOD, lt[RS] = (lt[RS] + lt[p]) % MOD;90 lt[p] = 0;91 }92 void Pushup(int p){93 st[p] = (st[LS] + st[RS]) % MOD;94 }95 void Build(int p = 1, int gl = 1, int gr = N){96 if(gl == gr){97 // printf("st[%d] <- idx[%d] = %d\n", p, gl, idx[gl]->val);98 return (void)(st[p] = idx[gl = gr]->val);99 }100 Build(LS, gl, MID);101 Build(RS, MID + 1, gr);102 Pushup(p);103 }104 void Modify(int l, int r, int val, int p = 1, int gl = 1, int gr = N){105 if(l <= gl && gr <= r)return (void)(st[p] = (st[p] + SIZ * val) % MOD, lt[p] = (lt[p] + val) % MOD);106 if(lt[p])Pushdown(p, gl, gr);107 if(l <= MID)Modify(l, r, val, LS, gl, MID);108 if(r >= MID + 1)Modify(l, r, val, RS, MID + 1, gr);109 Pushup(p);110 }111 ll Query(int l, int r, int p = 1, int gl = 1, int gr = N){112 if(l <= gl && gr <= r)return st[p];113 if(lt[p])Pushdown(p, gl, gr);114 return(115 (l <= MID ? Query(l, r, LS, gl, MID) : 0) +116 (r >= MID + 1 ? Query(l, r, RS, MID + 1, gr) : 0)117 ) % MOD;118 }119 void Desc(void){120 int cur(0);121 for(int i = 1; i <= 1 << 4; i <<= 1)122 for(int j = 1; j <= i; ++j)printf("%lld%c", st[++cur], j == i ? '\n' : ' ');123 }124}st;125
126127128
129void ModifyTree(Node* from, Node* to, int val){130 while(top(from) != top(to)){131 if(dep(top(from)) < dep(top(to)))swap(from, to);132 st.Modify(dfn(from->top), dfn(from), val);133 from = from ? from->top->fa : npt;134 }135 if(dep(from) < dep(to))swap(from, to);136 st.Modify(dfn(to), dfn(from), val);137}138ll QueryTree(Node* from, Node* to){139 ll ret(0);140 while(top(from) != top(to)){141 if(dep(top(from)) < dep(top(to)))swap(from, to);142 ret = (ret + st.Query(dfn(from->top), dfn(from))) % MOD;143 from = from ? from->top->fa : npt;144 }145 if(dep(from) < dep(to))swap(from, to);146 ret = (ret + st.Query(dfn(to), dfn(from))) % MOD;147 return ret;148}149
150int main(){151 // freopen("in.txt", "r", stdin);152 N = read(), M = read(), R = read(), MOD = read();153 for(int i = 1; i <= N; ++i)tr[i] = new Node(read());154 for(int i = 1; i <= N - 1; ++i){155 int f = read(), t = read();156 tr[f]->head = new Edge(tr[f]->head, tr[t]);157 tr[t]->head = new Edge(tr[t]->head, tr[f]);158 }159 dfs_pretreat(tr[R], npt);160 dfs_build(tr[R], tr[R]);161 st.Build();162 while(M--){163 int opt = read();164 switch(opt){165 case 1:{int f = read(), t = read(), val = read() % MOD; ModifyTree(tr[f], tr[t], val);break;}166 case 2:{int f = read(), t = read(); printf("%lld\n", QueryTree(tr[f], tr[t])); break;}167 case 3:{int x = read(), val = read() % MOD; st.Modify(tr[x]->dfn, tr[x]->dfn + tr[x]->siz - 1, val);break;}168 case 4:{int x = read(); printf("%lld\n", st.Query(tr[x]->dfn, tr[x]->dfn + tr[x]->siz - 1)); break;}169 }170 }171
172 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);173 return 0;174}175
176template<typename T>177inline T read(void){178 T ret(0);179 short flag(1);180 char c = getchar();181 while(c != '-' && !isdigit(c))c = getchar();182 if(c == '-')flag = -1, c = getchar();183 while(isdigit(c)){184 ret *= 10;185 ret += int(c - '0');186 c = getchar();187 }188 ret *= flag;189 return ret;190}update-2022_10_13 初稿