HYSBZ - 2243染色——樹鏈剖分+線段樹建樹技巧

【題目描述】
HYSBZ - 2243染色
在這里插入圖片描述
【題目分析】
我一直沒有看清楚題,以為求的是路徑上出現顏色的種類,然后就寫了一個區間染色的線段樹進行維護,過樣例的時候才發現題讀錯了,人家要求的是路徑上出現的顏色段,所以顏色的種類不重要,重要的是每一段每一段。理所當然,我們應該用線段樹維護所在區間有多少段。但是左右區間上傳的時候如果邊界顏色相同(左節點的右邊界和右節點的左邊界),那么區間個數應該減一。為此,我們還必須維護每個區間左邊界和右邊界分別是什么顏色以方便查詢和上傳。因為題目是區間修改,所以我們還要用lazy標記。(用lazy標記的時候要時時記得標記下傳,就是因為單點查詢的時候忘記要標記下傳wa了一下午)
因為在樹上,所以我們不僅僅需要判斷線段樹區間合并的時候左右端點顏色是否相同,還要判斷每條鏈頂和鏈頂的父節點的顏色是否相同,如果相同答案減一。(每條鏈都在向鏈頂合并)

【AC代碼】

#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<climits>using namespace std;const int MAXN=100005;	//時刻注意數據范圍
vector<int>g[MAXN];
int fa[MAXN],A[MAXN],val[MAXN],color[MAXN],pos[MAXN];
bool check[MAXN];
int siz[MAXN],son[MAXN],h[MAXN],top[MAXN];
int cnt=0,n,m;
int num[MAXN<<2],lazy[MAXN<<2];
int lc[MAXN<<2],rc[MAXN<<2];void dfs1(int u,int f)
{int i,v;siz[u]=1;son[u]=0;fa[u]=f;h[u]=h[f]+1;for(i=0;i<g[u].size();i++){v=g[u][i];if(v!=f){dfs1(v,u);siz[u]+=siz[v];if(siz[son[u]]<siz[v]) son[u]=v;}}
}
void dfs2(int u,int f,int k)
{int i,v;top[u]=k;pos[u]=++cnt;color[cnt]=val[u];if(son[u]) dfs2(son[u],u,k);for(i=0;i<g[u].size();i++){v=g[u][i];if(v!=f&&v!=son[u]) dfs2(v,u,v);}
}void pushup(int k)
{num[k]=num[k<<1]+num[k<<1|1];if(rc[k<<1]==lc[k<<1|1]) num[k]--;	//如果左右區間的連接處顏色相同則答案減一lc[k]=lc[k<<1]; rc[k]=rc[k<<1|1];
}void build(int k,int l,int r)
{if(l==r){num[k]=1;lc[k]=rc[k]=color[l];return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}void pushdown(int k)
{if(lazy[k]){lazy[k<<1]=lazy[k<<1|1]=lazy[k];lc[k<<1]=lc[k<<1|1]=lazy[k];rc[k<<1]=rc[k<<1|1]=lazy[k];num[k<<1]=num[k<<1|1]=1;lazy[k]=0;}
}void ColorChange(int k,int l,int r,int L,int R,int v)
{if(l>=L && r<=R){num[k]=1; lazy[k]=v;lc[k]=v; rc[k]=v;return;}int mid=(l+r)>>1;pushdown(k);if(L<=mid) ColorChange(k<<1,l,mid,L,R,v);if(R>mid) ColorChange(k<<1|1,mid+1,r,L,R,v);pushup(k); 
}int QueryInterval(int k,int l,int r,int L,int R)
{if(L<=l && r<=R){return num[k];}int mid=(l+r)/2;pushdown(k);int ret=0;if(R<=mid) return QueryInterval(k<<1,l,mid,L,R);else if(L>mid) return QueryInterval(k<<1|1,mid+1,r,L,R);	//這里必須這樣寫,因為要考慮是否存在區間合并ret+=QueryInterval(k<<1,l,mid,L,R);ret+=QueryInterval(k<<1|1,mid+1,r,L,R);if(rc[k<<1]==lc[k<<1|1]) ret--;return ret;
}int QueryPointColor(int k,int l,int r,int x)
{if(l==r && l==x){return lc[k];}pushdown(k);	//因為這里忘記了.wocint mid=(l+r)>>1;if(x<=mid) return QueryPointColor(k<<1,l,mid,x);else return QueryPointColor(k<<1|1,mid+1,r,x);
}int Findnum(int u,int v)
{memset(check,0,sizeof(check));int ans=0;while(top[u]!=top[v]){if(h[top[u]]<h[top[v]]) swap(u,v);ans+=QueryInterval(1,1,n,pos[top[u]],pos[u]);//printf("ans=%d\n",ans);//printf("QueryPointColor(1,1,n,pos[%d])=%d\nQueryPointColor(1,1,n,pos[%d])=%d\n",top[u],QueryPointColor(1,1,n,pos[top[u]]),fa[top[u]],QueryPointColor(1,1,n,pos[fa[top[u]]]));if(QueryPointColor(1,1,n,pos[top[u]]) == QueryPointColor(1,1,n,pos[fa[top[u]]]))	//考慮鏈與鏈的合并ans--;u=fa[top[u]];}if(h[u]<h[v]) swap(u,v);ans+=QueryInterval(1,1,n,pos[v],pos[u]);//printf("ans=%d\n",ans);return ans;
}void update(int u,int v,int w)
{while(top[u]!=top[v]){if(h[top[u]]<h[top[v]]) swap(u,v);ColorChange(1,1,n,pos[top[u]],pos[u],w);u=fa[top[u]];}if(h[u]<h[v]) swap(u,v);ColorChange(1,1,n,pos[v],pos[u],w);
}int main()
{int a,b,c;char s[10];scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&val[i]);for(int i=1;i<n;i++){scanf("%d%d",&a,&b);g[a].push_back(b);g[b].push_back(a);}dfs1(1,0);dfs2(1,0,1);build(1,1,n);while(m--){scanf("%s",s);if(s[0]=='C'){scanf("%d%d%d",&a,&b,&c);update(a,b,c);}else if(s[0]=='Q') {scanf("%d%d",&a,&b);printf("%d\n",Findnum(a,b));}}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384115.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384115.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384115.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

右值引用與轉移語義

https://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/ 新特性的目的 右值引用 (Rvalue Referene) 是 C 新標準 (C11, 11 代表 2011 年 ) 中引入的新特性 , 它實現了轉移語義 (Move Sementics) 和精確傳遞 (Perfect Forwarding)。它的主要目的有兩個方面&#xff…

打動態庫和靜態庫

一.動態庫和靜態庫的定義 1.靜態庫 ????程序在編譯鏈接時把庫的代碼鏈接到可執行文件中。程序運行時就不再需要靜態庫 2.動態庫 ????程序在運行的時候才去鏈接動態庫的代碼&#xff0c;多個程序 共享使用代碼 3.動態鏈接 ????在執行文件之前&#xff0c;外部…

HYSBZ - 2157樹鏈剖分

【題目描述】 HYSBZ - 2157樹鏈剖分 【題目分析】 這道題給出的是邊權而不是點權&#xff0c;但是我們分析這個樹就會發現每個節點都只有一個父親&#xff0c;也就是每條邊的邊權都可以存放在兒子節點上&#xff0c;然后在遍歷路徑的時候我們在從前往后遍歷&#xff0c;但是注…

C++11中的右值引用

http://www.cnblogs.com/yanqi0124/p/4723698.html 在C98中有左值和右值的概念&#xff0c;不過這兩個概念對于很多程序員并不關心&#xff0c;因為不知道這兩個概念照樣可以寫出好程序。在C11中對右值的概念進行了增強&#xff0c;我個人理解這部分內容是C11引入的特性中最難以…

BZOJ2115XOR——線性基

【題目描述】 BZOJ2115XOR——線性基 【題目分析】 這道題看完以后很懵逼&#xff0c;人家要是走的很復雜呢&#xff1f;各種繞來繞去怎么辦&#xff1f; 首先我們應該注意到一個很明顯的道理&#xff1a;重復的路徑會和自身抵消&#xff0c;所以我們大可以隨便跑&#xff0c;…

單鏈表的相關操作

1.冒泡排序對單鏈表進行排序 void LinkListBubbleSort(LinkNode* head) {if(head NULL){ return;//空鏈表} if(head -> next NULL){ return;//只有一個結點} LinkNode* cur head;//趟數LinkNode* tail NULL;//尾指針LinkNode* tmp head;//次數for(; cur -…

socket網絡編程--epoll小結

http://www.cnblogs.com/wunaozai/p/3895860.html 以前使用的用于I/O多路復用為了方便就使用select函數&#xff0c;但select這個函數是有缺陷的。因為它所支持的并發連接數是有限的(一般小于1024)&#xff0c;因為用戶處理的數組是使用硬編碼的。這個最大值為FD_SETSIZE&#…

進程間通信(匿名管道)

1.進程通信的目的 (1) 數據傳輸: 一個進程需要將它的數據傳輸給另一個進程 ????(2) 資源共享: 多個進程之間共享同樣的資源 ????(3) 通知事件: 一個進程需要向另一個或一組進程發送消息, 通知它們發生了什么事情 2.管道 管道是一種進程之間通信的一種方式, 我們把從…

線性基入門

今天學習了神奇的線性基&#xff0c;主要是在解決異或問題時比較有用。 詳細的解釋和證明有大佬珠玉在前&#xff0c;如果感興趣可以移步 補充一下自己的理解&#xff1a; 可以聯系線性代數極大無關組進行理解&#xff0c;線性基就相當于異或的向量空間中的極大無關組&#xff…

單例模式及C++實現代碼

http://www.cnblogs.com/cxjchen/p/3148582.html 單例模式 單例模式&#xff0c;可以說設計模式中最常應用的一種模式了&#xff0c;據說也是面試官最喜歡的題目。但是如果沒有學過設計模式的人&#xff0c;可能不會想到要去應用單例模式&#xff0c;面對單例模式適用的情況&am…

UVALive - 8512——線段樹維護線性基

【題目描述】 UVALive - 8512XOR 【題目分析】 這種區間線性基的問題我們可以考慮用線段樹維護&#xff0c;線性基的合并的話就直接暴力合并 找到所在區間的線性基后再查找最大的數&#xff0c;我看網上的博客要說消除k的影響什么的&#xff0c;我覺得沒有什么必要&#xff0c;…

命名管道

1.命名管道的創建 (1) 通過命令創建 mkfifo filename (2)在程序中創建 int mkfifo(const char* filename, mode_t mode); 2. 命名管道和匿名管道的區別 (1)匿名管道由pipe函數創建并且打開 ????(2)命名管道有mkfifo函數創建由open函數打開 ????(3) fifo 之間的兩…

HYSBZ - 1101——莫比烏斯反演

【題目描述】 HYSBZ - 1101 【題目分析】 昨天測試出了一道差不多的題目&#xff0c;我只能想到暴力&#xff0c;各種優化&#xff0c;最后都是運行了好久TLE&#xff0c;最后才知道要用到莫比烏斯反演&#xff0c;就想著今天研究一下&#xff0c;得出的結論就是&#xff0c;我…

Linux下I/O多路轉接之select --fd_set

http://blog.csdn.net/li_ning_/article/details/52165993 fd_set 你終于還是來了&#xff0c;能看到這個標題進來的&#xff0c;我想&#xff0c;你一定是和我遇到了一樣的問題&#xff0c;一樣的疑惑&#xff0c;接下來幾個小時&#xff0c;我一定竭盡全力&#xff0c;寫出我…

BZOJ 2844 | HYSBZ - 2844albus就是要第一個出場——線性基

【題目描述】 BZOJ 2844 | HYSBZ - 2844albus 【題目分析】 題目的意思大概是給一個數列&#xff0c;他有2n個子集&#xff0c;每個子集的元素的異或和構成新的一個數列&#xff0c;排序后問數字Q在這個序列里面的下標。 假如題目是求所有元素的異或和構成一個集合就好弄了&…

CodeForces - 641ELittle Artem and Time Machine——map+樹狀數組

【題目描述】 CodeForces - 641ELittle Artem and Time Machine 【題目分析】 題目的意思大概是有三種操作 1.在時間t加入一個數字x 2.在時間t刪除一個數字x 3.詢問在時間t集合里面x的個數 雖然題目描述很簡單&#xff0c;但是t和x的范圍都是109&#xff0c;我一開始想到的是主…

I/O多路轉接之poll 函數

http://blog.csdn.net/li_ning_/article/details/52167224 poll 一、poll()函數&#xff1a; 這個函數是某些Unix系統提供的用于執行與select()函數同等功能的函數&#xff0c;自認為poll和select大同小異&#xff0c;下面是這個函數的聲明&#xff1a; [cpp] view plaincopy …

鏈表相關筆試面試題

1.判斷兩個鏈表是否相交 兩個鏈表是否相交可分為以下幾種情況 ????&#xff08;1&#xff09;兩個鏈表都不帶環&#xff0c;此時兩個鏈表所對應的最后一個節點是相等的 ????&#xff08;2&#xff09;兩個鏈表一個帶環&#xff0c;一個不帶環&#xff0c;兩個鏈表一定…

Linux經典問題—五哲學家就餐問題

http://m.blog.csdn.net/aspenstars/article/details/70149038 一、問題介紹 由Dijkstra提出并解決的哲學家進餐問題(The Dinning Philosophers Problem)是典型的同步問題。該問題是描述有五個哲學家共用一張圓桌&#xff0c;分別坐在周圍的五張椅子上&#xff0c;在圓桌上有五…

修改之前的myshell使之支持輸入輸出重定向

1.open函數 ????這個函數是打開一個文件&#xff08;文件名叫pathname),以 flag 權限打開&#xff0c;flag 包括了以下幾種 O_RDONLY&#xff08;只讀&#xff09;, O_WRONLY&#xff08;只寫&#xff09;, O_RDWR&#xff08;讀寫&#xff09;&#xff0c;當文件打開成…