BZOJ 2819 Nim 樹鏈剖分

2021-08-03 03:32:40 字數 2739 閱讀 4929

time limit: 20 sec  memory limit: 128 mb

submit: 2787  solved: 1040

[ submit

][status

][discuss

]著名遊戲設計師vfleaking,最近迷上了nim。普通的nim遊戲為:兩個人進行遊戲,n堆石子,每回合可以取其中某一堆的任意多個,可以取完,但不可以不取。誰不能取誰輸。這個遊戲是有必勝策略的。於是vfleaking決定寫乙個玩nim遊戲的平台來坑玩家。

為了設計漂亮一點的初始局面,vfleaking用以下方式來找靈感:拿出很多石子,把它們聚成一堆一堆的,對每一堆編號1,2,3,4,...n,在堆與堆間連邊,沒有自環與重邊,從任意堆到任意堆都只有唯一一條路徑可到達。然後他不停地進行如下操作:

1.隨機選兩個堆v,u,詢問若在v到u間的路徑上的石子堆中玩nim遊戲,是否有必勝策略,如果有,vfleaking將會考慮將這些石子堆作為初始局面之一,用來坑玩家。

2.把堆v中的石子數變為k。

由於vfleaking太懶了,他懶得自己動手了。請寫個程式幫幫他吧。

第一行乙個數n,表示有多少堆石子。

接下來的一行,第i個數表示第i堆裡有多少石子。

接下來n-1行,每行兩個數v,u,代表v,u間有一條邊直接相連。

接下來乙個數q,代表操作的個數。

接下來q行,每行開始有乙個字元:

如果是q,那麼後面有兩個數v,u,詢問若在v到u間的路徑上的石子堆中玩nim遊戲,是否有必勝策略。

如果是c,那麼後面有兩個數v,k,代表把堆v中的石子數變為k。

對於100%的資料:

1≤n≤500000, 1≤q≤500000, 0≤任何時候每堆石子的個數≤32767

其中有30%的資料:

石子堆組成了一條鏈,這3個點會導致你dfs時爆棧(也許你不用dfs?)。其它的資料dfs目測不會爆。

注意:石子數的範圍是0到int_max

對於每個q,輸出一行yes或no,代表對詢問的回答。

【樣例輸入】

51 3 5 2 5

1 53 5

2 51 4

6q 1 2

q 3 5

c 3 7

q 1 2

q 2 4

q 5 3

yesno

yesyes

yes

果斷鏈剖

線段樹維護疑惑和即可

只有單點修改 還比較好打

查詢寫錯 暴調兩小時 笑哭

#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef double db;

typedef long long ll;

inline int read()

while(ch<='9'&&ch>='0')

return x*f;

}inline void print(int x)

const int n=500100;

int n,ecnt,last[n],a[n];

struct edgee[n<<1];

inline void add(int u,int v)

;last[u]=ecnt;}

int fa[n],size[n],dfn[n],top[n],dep[n],pos[n],cnt;

void dfs1(int u)

}void dfs2(int u,int tp)

if(!k)return ;

dfs2(k,tp);

for(int i=last[u];i;i=e[i].nt) }

struct segtreetr[n*5];

inline void pushup(int k)

void build(int l,int r,int k)

int mid=l+r>>1;

build(l,mid,k<<1);build(mid+1,r,k<<1|1);

pushup(k);

}void modify(int k,int x,int val)

int mid=l+r>>1;

if(x<=mid)modify(k<<1,x,val);

else modify(k<<1|1,x,val);

pushup(k);

}int seg_xsum(int k,int x,int y)

inline void query(int u,int v)

if(dfn[u]ans^=seg_xsum(1,dfn[v],dfn[u]);

if(ans)puts("yes");else puts("no");

}int main()

dfs1(1);dfs2(1,1);build(1,n,1);

int m=read();

while(m--)

else query(x,y);

} return 0;}/*

51 3 5 2 5

1 53 5

2 51 4

6q 1 2

q 3 5

c 3 7

q 1 2

q 2 4

q 5 3

yesno

yesyes

yes*/

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

BZOJ 3306 樹 樹鏈剖分

和bzoj 3083比就是弱化版了。樣例都有點像?include include using namespace std const int n 100005,m n 3,inf 0x7fffffff int read int next m to m head n sz n son n top n ...

樹鏈剖分 bzoj2243

time limit 20 sec memory limit 512 mb submit 2492 solved 960 submit status 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色...