題目鏈結
狀態奇差無比,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 不相鄰,我們可以加入樹剖的修改操作,但是線段樹的修改操...