tag:樹上帶修莫隊
題意:樹上每個點有一種糖果,求\(\sum_c\sum_^v_c*w_i\)
其中c為糖果種類,\(cnt_c\)其為出現次數。
離線樹上帶修莫隊。
先進行樹上分塊。分塊內的詢問按照出發點、終止點、詢問id優先順序依次遞減排序。
對於樹上莫隊,其實就是在尤拉序上莫隊。因為尤拉序的性質,即每個節點子樹內的節點一定會經過兩次,我們就可以用乙個括號序列的方式在莫隊時消除子樹內無用節點的影響。
具體來說,序列長度為2*n,每乙個節點出入隊時我們異或它是否在隊中即可。也就是記錄每個點出隊和入隊的時間戳,然後在序列上修改。
注意,對於lca其實在尤拉序時是沒有包括的,所以我們需要單獨求一下lca的影響。但是如果乙個端點本身就是lca就不用啦。
但是!用指標實現也太low了,我們直接利用它的樹形結構莫隊就行(實際上就是我看錯了題解)
分塊和排序
int dfs(int x,int f)
} st[++top]=x;
return siz+1;
}//----------------
++_n;
while(top)belong[st[top--]]=_n;
inline bool operator < (const query&zp)const
inline void solve(int x,int y,ll &ans)
}
for(int i=1;i<=cntq;i++)
if(i==1)solve(q[i].u,q[i].v,ans);
else solve(q[i].u,q[i-1].u,ans),solve(q[i].v,q[i-1].v,ans);//保證繼承答案連續
int lca=lca(q[i].u,q[i].v);
reverse(lca,ans);
q[i].ans=ans;
reverse(lca,ans);//單獨計算,最後要消除影響。不要被繼承。
}
事實證明,這種寫法是真毒瘤,開了o2才勉強能過。
全**
#include#include#include#include#include#includeusing namespace std;
inline int read()
namespace star
} st[++top]=x;
return siz+1;
} inline int lca(int x,int y)
bool vis[maxn];
int num[maxn];
inline void reverse(const int& x,ll &ans)
inline void solve(int x,int y,ll &ans)
} inline void work()
if(i==1)solve(q[i].u,q[i].v,ans);
else solve(q[i].u,q[i-1].u,ans),solve(q[i].v,q[i-1].v,ans);
int lca=lca(q[i].u,q[i].v);
reverse(lca,ans);
q[i].ans=ans;
reverse(lca,ans);
} sort(q+1,q+1+cntq,cmp);
for(int i=1;i<=cntq;i++)printf("%lld\n",q[i].ans); }}
signed main()
寫了個假的(gxy稱之為非主流)樹上莫隊。再寫一道免得腦子了裝著奇怪的東西。
因為寫法毒瘤所以#define int long long會t飛。
大家千萬不要學非主流
題解 洛谷 P4074 WC2013 糖果公園
p4074 wc2013 糖果公園 給你一棵樹樹,點有點權,帶修改,每一次經過一種點權會有不同的貢獻 隨著經過次數再變 問你從乙個點到乙個點的貢獻和 樹上帶修莫隊。用 cnt i 表示 i 這個點的權值的出現次數。用 a i 表示 i 號點的權值。用 v i 表示一權值 i 的貢獻定值。用 v i ...
P4074 WC2013 糖果公園 樹上帶修莫隊
戳這裡檢視題面 julao口中的樹上帶修莫隊的板子題 這個題拆開來說就是 帶修莫隊 樹上莫隊 帶修莫隊是莫隊的最基本的一種,就是將詢問排序後,按時間戳將修改操作增加或減少 樹上莫隊有兩種寫法,分別是按照大小分塊和按照尤拉序分塊,這裡介紹用尤拉序分塊的寫法,通過尤拉序我們可以將樹上問題轉化為序列問題,...
P4074 WC2013 糖果公園 樹上帶修莫隊
戳這裡檢視題面 julao口中的樹上帶修莫隊的板子題 這個題拆開來說就是 帶修莫隊 樹上莫隊 帶修莫隊是莫隊的最基本的一種,就是將詢問排序後,按時間戳將修改操作增加或減少 樹上莫隊有兩種寫法,分別是按照大小分塊和按照尤拉序分塊,這裡介紹用尤拉序分塊的寫法,通過尤拉序我們可以將樹上問題轉化為序列問題,...