hdu 5274 數鏈剖分 /dfs+數狀陣列
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<algorithm> #include<string> using namespace std; const int mmax = 100010; const int inf=0x3fffffff; struct edge { int st,en; int next; }E[2*mmax]; int p[mmax],fa[mmax],son[mmax],top[mmax],ID[mmax]; int deep[mmax],id_[mmax]; bool vis[mmax]; int w[mmax]; int num; void add(int st,int en) { E[num].st=st; E[num].en=en; E[num].next=p[st]; p[st]=num++; } void init() { memset(p,-1,sizeof p); num=0; } struct tree { int l,r; int sum; int mid() { return (l+r)>>1; } }T[4*mmax]; void build(int id,int l,int r) { T[id].l=l,T[id].r=r; if(l==r) { T[id].sum=w[ID[l]]; return ; } int mid=T[id].mid(); build(id<<1,l,mid); build(id<<1|1,mid+1,r); T[id].sum=T[id<<1].sum^T[id<<1|1].sum; } void updata(int id,int pos,int val) { if(T[id].l==T[id].r) { T[id].sum=val; return ; } int mid=T[id].mid(); if(mid>=pos) updata(id<<1,pos,val); else updata(id<<1|1,pos,val); T[id].sum=T[id<<1].sum^T[id<<1|1].sum; } int query(int id,int l,int r) { if(l<=T[id].l&&T[id].r<=r) return T[id].sum; int mid=T[id].mid(); int ans=0; if(mid>=l) ans^=query(id<<1,l,r); if(mid<r) ans^=query(id<<1|1,l,r); return ans; } int dfs(int u) { vis[u]=1; int cnt=1,tmp=0,e=0; for(int i=p[u];i+1;i=E[i].next) { int v=E[i].en; if(!vis[v]) { fa[v]=u; deep[v]=deep[u]+1; int tt=dfs(v); cnt+=tt; if(tmp<tt) { tmp=tt; e=v; } } } son[u]=e; return cnt; } int now_cnt; void new_id(int u) { ID[now_cnt]=u; id_[u]=now_cnt; now_cnt++; vis[u]=1; if(son[u]) { top[son[u]]=top[u]; new_id(son[u]); } for(int i=p[u];i+1;i=E[i].next) { int v=E[i].en; if(!vis[v]) new_id(v); } } int solve(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); ans^=query(1,id_[top[x]],id_[x]); x=fa[top[x]]; } if(deep[x]>deep[y]) swap(x,y); ans^=query(1,id_[x],id_[y]); return ans; } int main() { int n,q; int t; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&q); init(); for(int i=0;i<n-1;i++) { int u,v; scanf("%d %d",&u,&v); add(u,v); add(v,u); } for(int i=1;i<=n;i++) { scanf("%d",&w[i]); if(w[i]==0) w[i]=mmax; } fa[1]=1; deep[1]=0; memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) top[i]=i; dfs(1); memset(vis,0,sizeof vis); now_cnt=1; new_id(1); build(1,1,n); while(q--) { int d,x,y; scanf("%d %d %d",&d,&x,&y); if(d==0) { if(y==0) y=mmax; updata(1,id_[x],y); } else { if(x>y) swap(x,y); int tmp=solve(x,y); if(tmp==0) puts("-1"); else { if(tmp==mmax) tmp=0; printf("%d\n",tmp); } } } } return 0; }
第2種寫法 利用dfs序列
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<algorithm> #include<string> using namespace std; const int mmax = 100010; const int inf=0x3fffffff; struct edge { int st,en; int next; }E[2*mmax]; int p[mmax]; int w[mmax]; int num; void add(int st,int en) { E[num].st=st; E[num].en=en; E[num].next=p[st]; p[st]=num++; } void init() { memset(p,-1,sizeof p); num=0; } int Times; int deep[mmax],First[mmax],Last[mmax]; int C[mmax]; int fa[mmax][20]; int low_bit(int x) { return x&(-x); } int n; void update(int x) { for(int i=First[x];i<=n;i+=low_bit(i)) C[i]^=w[x]; for(int i=Last[x];i<=n;i+=low_bit(i)) C[i]^=w[x]; } int get_sum(int x) { int fg=0; for(int i=First[x];i>0;i-=low_bit(i)) fg^=C[i]; return fg; } void dfs(int u,int Deep) { Times++; First[u]=Times; deep[u]=Deep; for(int i=1;(1<<i)<=deep[u];i++) fa[u][i]=fa[ fa[u][i-1]][i-1]; for(int i=p[u];i+1;i=E[i].next) { int v=E[i].en; if(deep[v]==-1) { fa[v][0]=u; dfs(v,Deep+1); } } Last[u]=Times+1; } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=19;i>=0;i--) { if(fa[x][i]!=-1 && deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if(deep[x]==deep[y]) break; } if(x==y) return x; for(int i=19;i>=0;i--) { if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; } return fa[x][0]; } int main() { int q; int t; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&q); init(); for(int i=0;i<n-1;i++) { int u,v; scanf("%d %d",&u,&v); add(u,v); add(v,u); } for(int i=1;i<=n;i++) { scanf("%d",&w[i]); w[i]++; } Times=0; memset(deep,-1,sizeof deep); memset(fa,-1,sizeof fa); dfs(1,0); //cout<<lca(1,2)<<endl; //system("pause"); // for(int i=1;i<=n;i++) //cout<<First[i]<<" "<<Last[i]<<endl; memset(C,0,sizeof C); for(int i=1;i<=n;i++) update(i); // for(int i=1;i<=n;i++) // cout<<get_sum(i)<<" "; // cout<<endl; while(q--) { int d,x,y; scanf("%d %d %d",&d,&x,&y); if(d==0) { update(x); w[x]=(++y); update(x); } else { //cout<<lca(x,y)<<endl; int tmp=get_sum(x)^get_sum(y)^w[lca(x,y)]; tmp--; printf("%d\n",tmp); } } } return 0; }
相關推薦
hdu 5274 數鏈剖分 /dfs+數狀陣列
注意 第一:點權為0.。。。 第 2:杭電擴充套件啊。。。 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include<stdio.h>
hdu 5044 Tree (樹鏈剖分+標記數組)
chan main while class #define AR spa def ble 鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5044 這道題是真的有毒,之前用樹鏈剖分+線段樹寫,tle了一萬發,瘋狂優化,最後放棄了,
樹鏈剖分套樹狀數組(區間修改)板子
c代碼 msu style ont 重要 pri ott src inline P3384 【模板】樹鏈剖分 題目描述 如題,已知一棵包含N個結點的樹(連通且無環),每個節點上包含一個數值,需要支持以下操作: 操作1: 格式: 1 x y z 表示將樹從x到y結點最短
HDU 5052 /// 樹鏈剖分+線段樹區間合併
題目大意: 給定n (表示樹有n個結點) 接下來n行給定n個點的點權(在這個點上買雞或者賣雞的價錢就是點權) 接下來n-1行每行給定 x y 表示x結點和y結點之間有一條邊 給定q (表示有q個詢問) 接下來q行 每行給定 x y v 查詢x到y的路徑上 先買雞再賣雞能夠贏得的最大利潤 買賣完後
BZOJ_P4196 [NOI2015]軟體包管理器(樹鏈剖分+dfs序)
Linux 使用者和 OS X 使用者一定對軟體包管理器不會陌生。通過軟體包管理器,你可以通過一行命令安裝某一個軟體包,然後軟體包管理器會幫助你從軟體源下載軟體包,同時自動解決所有的依賴(即下載安裝這個軟體包的安裝所依賴的其它軟體包),完成所有的配置。Deb
HDU 3966 樹鏈剖分後線段樹維護
!= node const == void sin bsp div str 題意: 一棵樹, 操作1.$path(a,b)$之間的點權$+k$ 操作2.單點查詢 題解: 樹鏈剖分即可,註意代碼細節,雙向映射 主要是記錄一下板子 #include
HDU 6162 樹鏈剖分
its 一個 += ++ ons match 思路 eof query 題意:給你一顆樹,每個節點有有一個權值,每次詢問從x到y的最短路上權值在c到d之間的所有的點的權值和是多少。 思路:肯定要用樹剖,因為詢問c到d之間這種操作樹上倍增很難做,但是用其它數據結構可以比較好
BZOJ_4034 [HAOI2015]樹上操作 【樹鏈剖分dfs序+線段樹】
for d+ ems ans bit mil href 編號 lazy 一 題目 [HAOI2015]樹上操作 二 分析 樹鏈剖分的題,這裏主要用到了$dfs$序,這題比較簡單的就是不用求$lca$。 1.和樹鏈剖分一樣,先用鄰接鏈表建雙向圖。 2
【BZOJ2843】極地旅行社 離線+樹鏈剖分+樹狀數組
i++ data 代碼 == 範圍 cst string input 樹狀 【BZOJ2843】極地旅行社 Description 不久之前,Mirko建立了一個旅行社,名叫“極地之夢”。這家旅行社在北極附近購買了N座冰島,並且提供觀光服務。
Aragorn's Story 樹鏈剖分+線段樹 && 樹鏈剖分+樹狀數組
date shu 更新 none ++ span display struct mem Aragorn‘s Story 來源:http://120.78.128.11/Problem.jsp?pid=2710 來源:http://acm.hdu.edu.cn/showpro
UOJ268 [清華集訓2016] 數據交互 【動態DP】【堆】【樹鏈剖分】【線段樹】
auto 合並 -s 樹形dp lazy tail clas 記錄 less 題目分析: 不難發現可以用動態DP做。 題目相當於是要我求一條路徑,所有與路徑有交的鏈的代價加入進去,要求代價最大。 我們把鏈的代價分成兩個部分:一部分將代價加入$LCA$之中,用$g$數組保存;
BZOJ4448 SCOI2015情報傳遞(離線+樹鏈剖分+樹狀數組)
fin tree amp tdi 開始 情報 路徑 stream from 即滋磁單點修改,詢問路徑上小於某數的值有多少個。暴力樹剖套個主席樹即可,然而不太優美。 開始覺得可以cdq,然而就變成log^3了。冷靜一下感覺簡直是個弱智,修改本身就是單調的,只要對詢問離
Gym - 101630L Laminar Family (樹鏈剖分維護區間出現的段數)
解題思路:先把每個查詢的距離從大到小排序,然後我們再列舉查詢,這樣就不用考慮包含的情況了,因為小的肯定可以被大的包含,因此我們就只用考慮相交的情況了,關於相交,我們用區間染色的思想,然後查詢區間出現的顏色個數即可,我這裡用的是區間查詢顏色段數。 #include<
101630L Laminar Family (樹鏈剖分維護區間出現的段數)
解題思路:先把每個查詢的距離從大到小排序,然後我們再列舉查詢,這樣就不用考慮包含的情況了,因為小的肯定可以被大的包含,因此我們就只用考慮相交的情況了,關於相交,我們用區間染色的思想,然後查詢區間出現的顏色個數即可,我這裡用的是區間查詢顏色段數。 #include&l
HDU 5221 Occupation dfs序版樹鏈剖分
題目大意: 就是現在給出一棵樹, 以1為根, 樹上的點都有自己的權值, 初始都沒有被佔領, 接下來3種操作 1. 從u到v的路徑上的所有點被M佔領 2. 某個點u被C佔領 3. 以u為根的子樹被M佔領 每次操作後輸出當前被M佔領的那些點的點權和 大致思路: 很明顯對於操作
HDU 5044 Tree(樹鏈剖分)
int str ans hang line sin _id rgb php HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai
HDU-3966 Aragorn's Story(樹鏈剖分+線段樹)
real letter 們的 等等 then 需要 family sea inpu Aragorn‘s Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot
HDU Aragorn's Story -樹鏈剖分
next font scanf ont change desc one proc php HDU Aragorn‘s Story Problem Descript
hdu 6162 Ch’s gift(樹鏈剖分+主席樹)
spl memset show pen 路徑 esp ems href lan 題目鏈接:hdu 6162 Ch’s gift 題意: 給你一棵樹,樹上每個點有一個權值,現在有m個詢問,每次詢問給你一個s,t,L,R,問你從s到t的路徑上,權值在[L,R]內的總和為多少。
HDU 5893 List wants to travel(樹鏈剖分+線段樹)
color top ons set 基本 brush [0 pri cto 題目鏈接 HDU5893 2016年ICPC沈陽網絡賽的B題。這道題其和 BZOJ2243 基本一樣 那道題我也寫了題解 點這裏 兩道題的區別就是BZOJ這題是點的權值,這道題是邊權。 所以