思路:
抄一波yousiki的…
顯然,暴力求解的複雜度是無法承受的。考慮這樣的一種暴力,我們把 z 到根上的點全部打標記,對於 l 到 r 之間的點,向上搜尋到第乙個有標記的點求出它的深度統計答案。觀察到,深度其實就是上面有幾個已標記了的點(包括自身)。所以,我們不妨把 z 到根的路徑上的點全部 +1,對於 l 到 r 之間的點詢問他們到根路徑上的點權和。仔細觀察上面的暴力不難發現,實際上這個操作具有疊加性,且可逆。也就是說我們可以對於 l 到 r 之間的點 i,將 i 到根的路徑上的點全部 +1, 轉而詢問 z 到根的路徑上的點(包括自身)的權值和就是這個詢問的答案。把詢問差分下,也就是用 [1, r] − [1, l − 1] 來計算答案,那麼現在我們就有乙個明顯的解法。從 0 到 n − 1 依次插入點 i,即將 i 到根的路徑上的點全部+1。離線詢問答案即可。我們現在需要乙個資料結構來維護路徑加和路徑求和,顯然樹鏈剖分或lct 均可以完成這個任務。樹鏈剖分的複雜度為 o((n + q)· log n · log n),lct的複雜度為 o((n + q)· log n),均可以完成任務。至此,題目已經被我們完美解決。
//by siriusren
#include
#include
#include
using namespace std;
#define int long long
#define n 100050
int n,q,v[n],first[n],next[n],tot,all,cnt;
int fa[n],deep[n],son[n],size[n],top[n],p[n];
void add(int
x,int
y)struct nodenode[n];
struct treetr[n*8];
bool cmp(node a,node b)
bool cmp(node a,node b)
}void dfs2(int
x,int tp)
void push_down(int
pos,int num)
void insert(int l,int r,int
pos,int l,int r)
if(tr[pos].lazy)push_down(pos,r-l+1);
int mid=(l+r)>>1,lson=pos
<<1,rson=pos
<<1|1;
if(mid1,r,rson,l,r);
else
if(mid>=r)insert(l,mid,lson,l,r);
else insert(l,mid,lson,l,r),insert(mid+1,r,rson,l,r);
tr[pos].sum=tr[lson].sum+tr[rson].sum;
}void ins(intx)}
int query(int l,int r,int
pos,int l,int r)
int qry(int
x)return ans;
}signed main()
sort(node+1,node+1+all,cmp);
dfs(1),dfs2(1,1);
int temp=1;
while(node[temp].pos==0)temp++;
for(int i=1;i<=n;i++)
sort(node+1,node+1+all,cmp);
for(int i=1;i<=all;i+=2)printf("%lld\n",(node[i+1].ans-node[i].ans)%201314);
}
bzoj 3626 神思維 鏈剖 線段樹
emmmm這道題的思路實在是神。雖然做過然而做過一遍還是做不出來。本來還想到了另外一種思路。不過寫完調來調去發現這個思路完全是錯的qaq要是這樣把隊友坑了那怎麼行qaq 繼續貼清華爺gconeice的題解。顯然,暴力求解的複雜度是無法承受的。考慮這樣的一種暴力,我們把 z 到根上的點全部打標記,對於...
樹剖想法題 BZOJ3626
本來是打算作為樹剖練習的最後一題的,結果一直wa。本來以為是自己寫的太醜。最後發現5w的資料 我開了10w的陣列 然而有乙個陣列要 2 哦,好棒棒。1 include2 include3 include4 include5 define foru i,x,y for ll i x i y i 6us...
bzoj 3626 LCA(樹鏈剖分)
傳送門biu 考慮求lca x,y 的深度,可以把 x 到根路徑上的所有節點權值加一,再查詢 y到根路徑上的所有節點的權值和即為lc a x,y 的深度。將詢問離線,把詢問 r i ld eplc a i,z 拆成兩個詢問 r i 1d eplc a i,z 減去 l 1i 1dep lca i,z...