簡單起見,你就是要處理下面三件事,所有的事件都是按照時間順序給出的。
q p q
從第 pp 個部落出發的建築工人想知道能否到達第 qq 個部落了,你要回答的便是yes
/no
,注意大小寫。
c p q
第 pp 個部落與第 qq 個部落開戰了,保證他們一定是相鄰的部落,且目前處於停戰(未開戰)狀態。
u x
第 xx 次發生的戰爭結束了,它將永遠的被載入史冊,不復存在(保證這個訊息不會告訴你多次)
第一行兩個數 nn 和 mm, nn 代表了一共有 nn 個部落,mm 代表了以上三種事件發生的總數。
接下來的 n - 1n−1 行,每行兩個數 p, qp,q,代表了第 pp 個部落與第 qq 個部落之間有一條道路相連。
接下來的 mm 行,每行表示一件事,詳見題目描述。
每行乙個yes
或者no
,表示從第 pp 個部落出發的建築工人能否到達第 qq 個部落。
#includeusingnamespace
std;
const
int maxn=3e5+100
;vector
g[maxn];
struct
war war[maxn];
intn,m;
intson[maxn];
intid[maxn];
intfa[maxn];
intcnt;
intdep[maxn];
intsize[maxn];
inttop[maxn];
intw[maxn];
intwt[maxn];
struct
node segtree[maxn*4
];void build (int i,int l,int
r)
int mid=(l+r)>>1
; build(i
<<1
,l,mid);
build(i
<<1|1,mid+1
,r);
segtree[i].sum=segtree[i<<1].sum+segtree[i<<1|1
].sum;
}void spread (int
i) }
void update (int i,int l,int r,int
val)
spread(i);
int mid=(segtree[i].l+segtree[i].r)>>1
;
if (l<=mid)
update(i
<<1
,l,r,val);
if (r>mid)
update(i
<<1|1
,l,r,val);
segtree[i].sum=segtree[i<<1].sum+segtree[i<<1|1
].sum;
}int query (int i,int l,int
r) int qrange (int x,int
y)
if (dep[x]>dep[y]) swap(x,y);
ans+=query(1,id[x]+1
,id[y]);
return
ans;
}void uprange (int x,int y,int
k)
if (dep[x]>dep[y]) swap(x,y);
update(
1,id[x]+1
,id[y],k);
}void dfs1 (int x,int f,int
deep)
}void dfs2 (int x,int
topf)
}int
main ()
dfs1(
1,0,1
); dfs2(
1,1);
build(
1,1,n);
int tot=0
;
for (int i=1;i<=m;i++)
else
if (s=="c"
) ; uprange(x,y,1);
}else
if (s=="u"
) }
}
luogu題解 P3950部落衝突 樹鏈剖分
大佬都用lct,我太弱只會樹鏈剖分 乙個很裸的維護邊權樹鏈剖分題.按照套路,對於一條邊 dep u 讓它邊權加1就在 v 點處 1,將邊的問題轉化為點的問題 然後對於c,u操作,線段樹單點修改,q操作區間查詢 include include include include include inclu...
P3950 部落衝突
此題用樹鏈剖分是大材小用了,因為它可以處理 p,q 不相鄰的情況。簡化一下題意 這都是一些樹上的操作,乍一看可以用樹剖直接搞。但是因為這裡是邊進行操作,所以我們可以以點代邊,把邊看做點。每一次查詢的時候 lca p,q 是不能算的。如果 p,q 不相鄰,我們可以加入樹剖的修改操作,但是線段樹的修改操...
洛谷 P3950 部落衝突(樹鏈剖分 樹狀陣列)
p3950 部落衝突 給一棵樹,q操作是u,v是否可達,c操作是u,v間的簡單路徑不可走,u是撤銷第i個c操作。樹鏈剖分 樹狀陣列。樹鏈剖分點權改邊權,對於u,v間的簡單路徑不可走可以邊權都加1,撤銷就是邊權都減1,詢問就樹狀陣列維護區間和,0就可達。題目限制保證了思路合法。題面裡保證兩點相鄰不是有...