Luogu P3950部落衝突(樹鏈剖分)

2022-05-01 01:12:16 字數 2110 閱讀 3940

題目鏈結

狀態奇差無比,sbt都能錯一遍。

不動筆光想沒有想到怎麼做,畫圖之後發現乙個很明顯的性質……

那就是兩個開戰的部落,其中乙個是另乙個的父親。

所以在兒子那裡加個權值。查詢的時候樹鏈剖分查詢鏈上點權和,減去lca的點權(因為lca那如果有點權,代表的是lca和lca的父親之間的那條邊)。

#include#include

#include

#include

#include

#define left (rt<<1)

#define right (rt<<1|1)

#define mid ((l+r)>>1)

#define lson l,mid,left

#define rson mid+1,r,right

#define maxn 300050

using

namespace

std;

inline

long

long

read()

while

(isdigit(ch))

return num*f;

}struct

edgeedge[maxn*3

];int

head[maxn],num;

inline

void add(int

from,int

to);

head[

from]=num;

}int tree[maxn*4

];int

dfn[maxn];

intdeep[maxn];

intfather[maxn];

intsize[maxn];

inttop[maxn];

intson[maxn];

intid,n,m;

void unifnd(int x,int

fa)}

void unionn(int x,int

top)

}inline

void pushup(int

rt)void update(int o,int num,int l,int r,int

rt)

if(o<=mid) update(o,num,lson);

else

update(o,num,rson);

pushup(rt);

return;}

int query(int

from,int to,int l,int r,int

rt)struct

warq[maxn];

intcnt;

inline

void adds(int

from,int

to);

update(dfn[

from],1,1,n,1

);

return;}

inline

void del(int

rnk)

inline

int lca(int

from,int

to)

if(deep[from]>deep[to]) swap(from

,to);

return

from;}

inline

int ask(int

from,int

to)

if(deep[from]>deep[to]) swap(from

,to);

ans+=query(dfn[from],dfn[to],1,n,1

);

if(ans>0) return0;

return1;

}int

main()

unifnd(

1,1);

unionn(

1,1);

for(int i=1;i<=m;++i)

else

if(c[0]=='c'

)

else

}return0;

}

luogu P3950 部落衝突

題面傳送門 樹剖裸題,感覺難度虛高。當兩個部落開戰時,我們就把下面那個點的權值設為1 11,休戰則設為0 00即可。這樣有乙個好處就是查詢時如果有1 11可以直接跳出。其他基本操作。實現 include include using namespace std int n,m,k,f 600039 x...

luogu P3950 部落衝突 題解

題目連線 1.像我這種學資料結構學傻了的 2.邊權化點權 所有點權初始化0 3.對於戰爭 將深度較深的 1,對於和平 將深度較深的 1 4.對於歷史 用war記錄 5.特別注意 在兩個查詢的lca處判斷是否為 1並且當前的整條路徑上的點權也為 1時 同樣是yes using namespace st...

P3950 部落衝突

此題用樹鏈剖分是大材小用了,因為它可以處理 p,q 不相鄰的情況。簡化一下題意 這都是一些樹上的操作,乍一看可以用樹剖直接搞。但是因為這裡是邊進行操作,所以我們可以以點代邊,把邊看做點。每一次查詢的時候 lca p,q 是不能算的。如果 p,q 不相鄰,我們可以加入樹剖的修改操作,但是線段樹的修改操...