解題思路:
先鏈剖。
維護線段樹時每個節點維護三個值:lc(左端點顏色),rc(右端點顏色),cnt(區間中顏色段數量)。
注意每次合併區間時(詳見**中update,query,query函式),若左區間rc等於右區間lc是結果要減1;
修改時打標記即可,注意tag初始要賦值為-1,因為有color為0的情況。
#include
#include
#include
#include
#include
using namespace std;
int getint()
const int n=100005;
int n,m,a[n];
int ecnt,first[n],next[n<<1],to[n<<1];
int fa[n],dep[n],son[n],size[n],top[n],pos[n],idx[n];
int tot,cnt[n<<2],lc[n<<2],rc[n<<2],tag[n<<2];
void add(int
x,int
y)void dfs1(int u)
}void dfs2(int u)
for(int e=first[u];e;e=next[e])
}void update(int k)
void build(int k,int l,int r)
int mid=l+r>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
update(k);
}void pushdown(int k)
void modify(int k,int l,int r,int
x,int
y,int c)
if(tag[k]!=-1)pushdown(k);
int mid=l+r>>1;
if(y
<=mid)modify(k<<1,l,mid,x,y,c);
else
if(x>mid)modify(k<<1|1,mid+1,r,x,y,c);
else modify(k<<1,l,mid,x,mid,c),modify(k<<1|1,mid+1,r,mid+1,y,c);
update(k);
}int find(int k,int l,int r,int p)
int query(int k,int l,int r,int
x,int
y)void modify(int u,int v,int c)
if(dep[u]>dep[v])swap(u,v);
modify(1,1,n,pos[u],pos[v],c);
}int query(int u,int v)
if(dep[u]>dep[v])swap(u,v);
res+=query(1,1,n,pos[u],pos[v]);
return res;
}int main()
dfs1(1);
tot=top[1]=pos[1]=idx[1]=1;
dfs2(1);
build(1,1,n);
while(m--)
else
}return
0;}
bzoj2243染色 樹鏈剖分 線段樹
time limit 20 sec memory limit 512 mb submit 8230 solved 3073 submit status discuss 給定一棵有 n個節點的無根樹和 m個操作,操作有2類 1 將節點 a到節點 b路徑上所有點都染成顏色c 2 詢問節點 a到節點 b路...
bzoj 2243 染色 樹鏈剖分
首先這是個挺裸的題,由於太久沒寫剖分導致調了好久,前天調了一下午,一直查不到錯 昨晚在看春晚的時候突然靈機一動,發現合併的時候出了問題,開電腦把它a掉了 感覺自己也蠻拼的給定 一棵有n 個節點的 無根樹和 m個操作 操作有 2類 1 將節點a 到節點b 路徑上所 有點都染 成顏色c 2 詢問節點a ...
bzoj 2243 樹鏈剖分 染色
time limit 20 sec memory limit 512 mb submit 3205 solved 1238 submit status discuss 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段...