【點分治】luoguP2664 樹上游戲

應該是一道中等難度的點分?麻煩在一些細節。

題目描述

lrb有一棵樹,樹的每個節點有個顏色。給一個長度為n的顏色序列,定義s(i,j) 為i 到j 的顏色數量。以及

現在他想讓你求出所有的sum[i]

輸入輸出格式

輸入格式:

第一行為一個整數n,表示樹節點的數量

第二行為n個整數,分別表示n個節點的顏色c[1],c[2]……c[n]

接下來n-1行,每行為兩個整數x,y,表示x和y之間有一條邊

輸出格式:

輸出n行,第i行為sum[i]

說明

sum[1]=s(1,1)+s(1,2)+s(1,3)+s(1,4)+s(1,5)=1+2+3+2+2=10
sum[2]=s(2,1)+s(2,2)+s(2,3)+s(2,4)+s(2,5)=2+1+2+1+3=9
sum[3]=s(3,1)+s(3,2)+s(3,3)+s(3,4)+s(3,5)=3+2+1+2+3=11
sum[4]=s(4,1)+s(4,2)+s(4,3)+s(4,4)+s(4,5)=2+1+2+1+3=9
sum[5]=s(5,1)+s(5,2)+s(5,3)+s(5,4)+s(5,5)=2+3+3+3+1=12

對于40%的數據,n<=2000

對于100%的數據,1<=n,c[i]<=10^5


題目分析

想法一:按顏色拆貢獻

這里應該是有一種小顏色大顏色的分塊套路的。但是這個想法我只能解決全局路徑的數量和,并不會落實到點的詢問。

想法二:點分治

目前尚未歸結出點分治適用的具體問題范圍……不過這一題是可以用點分解決的。

考慮每一層點分樹,我們只需要對它的節點處理貢獻。這里的貢獻分為兩部分:重心答案;經過重心的路徑對子樹的貢獻。

重心的答案只需要以它自身為根,遍歷一邊該層點分樹即可。子樹內的答案處理要略微麻煩一些,需要分顏色來考慮貢獻。記$colCnt[i]$為所有以重心為起點的路徑中,含有顏色$i$的路徑條數。然后首先假定子樹內所有點的答案都為$\sum colCnt[i]$,再容斥考慮重心到子樹路徑上的顏色所產生的貢獻。

記當前點分樹中除去正在處理的子樹的大小為$outTot$,那么對于子樹內點$x$,由于它具有顏色$c[x]$,所以對自身的答案有一個$outTot-colCnt[c[x]]$的貢獻。并且,這一個貢獻對于$x$的子樹也是一概適用的,所以這一個標記要差分式地下傳。

整體思路就是這些。這一題的點分涉及到例如“子樹結構的重定向”或是“兩個顏色桶并存”的一些細節問題,所以實現上面可能有一定的難度。

(話說這題的碼風怎么這么丑)

?

  1 #include<bits/stdc++.h>
  2 typedef long long ll;
  3 const int maxn = 100035;
  4 const int maxm = 200035;
  5 
  6 ll ans[maxn];
  7 int n,bloTot,outTot,c[maxn]; 
  8 int size[maxn],son[maxn],root;
  9 int edgeTot,head[maxn],nxt[maxm],edges[maxm];
 10 int cols,cnt,cl,col[maxn],colTmp[maxn],colTim[maxn],colCnt[maxn],subCnt[maxn];
 11 bool colEx[maxn],divEx[maxn];
 12 
 13 int read()
 14 {
 15     char ch = getchar();
 16     int num = 0, fl = 1;
 17     for (; !isdigit(ch); ch=getchar())
 18         if (ch=='-') fl = -1;
 19     for (; isdigit(ch); ch=getchar())
 20         num = (num<<1)+(num<<3)+ch-48;
 21     return num*fl;
 22 }
 23 void addedge(int u, int v)
 24 {
 25     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
 26     edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
 27 }
 28 void getRoot(int x, int fa)
 29 {
 30     size[x] = 1, son[x] = 0;
 31     for (int i=head[x]; i!=-1; i=nxt[i])
 32     {
 33         int v = edges[i];
 34         if (divEx[v]||v==fa) continue;
 35         getRoot(v, x), size[x] += size[v];
 36         son[x] = std::max(son[x], size[v]);
 37     }
 38     son[x] = std::max(son[x], bloTot-size[x]);
 39     if (son[x] < son[root]) root = x;
 40 }
 41 void colDfs(int x, int fa, int *cnt)
 42 {
 43     if (!colEx[c[x]]) colEx[c[x]] = 1, col[++cols] = c[x];
 44     if ((++colTim[c[x]])==1) cnt[c[x]] += size[x];
 45     for (int i=head[x]; i!=-1; i=nxt[i])
 46         if ((!divEx[edges[i]])&&(edges[i]!=fa))
 47             colDfs(edges[i], x, cnt);
 48     --colTim[c[x]];
 49 }
 50 void colClear()
 51 {
 52     for (int i=1; i<=cl; i++) colEx[colTmp[i]] = 0;
 53     cols = 0;
 54 }
 55 void modify(int x, int fa, ll tag)
 56 {
 57     if ((++colTim[c[x]])==1) tag += outTot-colCnt[c[x]];
 58     ans[x] += tag+cnt;
 59     for (int i=head[x]; i!=-1; i=nxt[i])
 60     {
 61         int v = edges[i];
 62         if (v==fa||divEx[v]) continue;
 63         modify(v, x, tag);
 64     }
 65     --colTim[c[x]];
 66 }
 67 void calc(int rt)      //核心操作在這里
 68 {
 69     colClear(), getRoot(rt, 0);
 70     colDfs(rt, 0, colCnt);
 71     cnt = 0, cl = cols;
 72     for (int i=1; i<=cols; i++)
 73         cnt += colCnt[col[i]], colTmp[i] = col[i];
 74     ans[rt] += cnt;
 75     for (int i=head[rt]; i!=-1; i=nxt[i])
 76     {
 77         int v = edges[i];
 78         if (divEx[v]) continue;
 79         for (int j=1; j<=cl; j++) subCnt[colTmp[j]] = 0;  //及時清除數組
 80         colClear();
 81         colEx[c[rt]] = 1;
 82         colDfs(v, rt, subCnt);          //統計子樹內的含顏色i路徑條數
 83         colEx[c[rt]] = 0;
 84         colCnt[c[rt]] -= size[v], cnt -= size[v];   //除去重心出發的路徑
 85         for (int j=1; j<=cols; j++)
 86         {
 87             colCnt[col[j]] -= subCnt[col[j]];  //除去子樹內的路徑(因為考慮子樹外路徑)
 88             cnt -= subCnt[col[j]];
 89         }
 90         outTot = size[rt]-size[v], modify(v, rt, 0);  //對子樹內累加貢獻
 91         colCnt[c[rt]] += size[v], cnt += size[v];    //恢復處理子樹前狀態
 92         for (int j=1; j<=cols; j++)
 93         {
 94             colCnt[col[j]] += subCnt[col[j]];
 95             cnt += subCnt[col[j]];
 96         }
 97     }
 98     for (int i=1; i<=cl; i++)
 99         colCnt[colTmp[i]] = 0;      //colTmp[]的作用;清空colCnt[]
100 }
101 void deal(int rt)
102 {
103     calc(rt), divEx[rt] = 1;
104     for (int i=head[rt]; i!=-1; i=nxt[i])
105     {
106         int v = edges[i];
107         if (divEx[v]) continue;
108         root = 0, bloTot = size[v];
109         getRoot(v, 0), deal(root);
110     }
111 }
112 int main()
113 {
114     memset(head, -1, sizeof head);
115     n = read(), son[0] = n;
116     for (int i=1; i<=n; i++) c[i] = read();
117     for (int i=1; i<n; i++) addedge(read(), read());
118     bloTot = n, getRoot(1, 0), deal(root);
119     for (int i=1; i<=n; i++) printf("%lld\n",ans[i]);
120     return 0;
121 }

?

?

?

END

轉載于:https://www.cnblogs.com/antiquality/p/10339899.html

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

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

相關文章

EasyJoyStick使用以及兩種操作桿 EasyJoyStick的使用方法,簡單的不能再簡單 Hedgehog Team-》Easy Touch -》Add Easy Touch For C#

EasyJoyStick使用以及兩種操作桿EasyJoyStick的使用方法&#xff0c;簡單的不能再簡單Hedgehog Team-》Easy Touch -》Add Easy Touch For C#Hedgehog Team-》Easy Touch -》Extensions-》Adding A New Joystick配置如圖&#xff1a;然后看一下配置&#xff0c;我喜歡掌控性強一…

2.1 vector

表結構的數組實現隨機訪問快速尾插動態調整所占內存空間#include<vector>從0開始計數創建vector對象的三種方法&#xff1a; 1. vector<int> v;2. vector<int> v(10); //默認值為03. vecotr<double> v(10,8.6); //為每個元素指定初始值尾插&#xff1a…

文件系統管理 之 文件和目錄訪問權限設置

一、文件和目錄權限概述 在linux中的每一個文件或目錄都包含有訪問權限&#xff0c;這些訪問權限決定了誰能訪問和如何訪問這些文件和目錄。 通過設定權限可以從以下三種訪問方式限制訪問權限&#xff1a;只允許用戶自己訪問&#xff1b;允許一個預先指定的用戶組中的用戶訪問&…

Web滲透實驗:基于Weblogic的一系列漏洞

1. 攻擊機windows10 192.168.2.104 2. 靶機ip: 192.168.2.109(linux Ubantu) 192.168.2.111(windows2008R264位) 第一步&#xff1a;啟動靶機服務 分別為linux和windows windows環境搭建&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/16KyYb1v1rP9uJ6-5MBotVw   提取…

9 月 19 日,騰訊云安全中心監測到 ?Apache Tomcat 修復了2個嚴重級別的漏洞, 分別為: 信息泄露漏洞(CVE-2017-12616)、遠程代碼執行漏洞(CVE-2017-12615

9 月 19 日&#xff0c;騰訊云安全中心監測到 Apache Tomcat 修復了2個嚴重級別的漏洞&#xff0c; 分別為&#xff1a; 信息泄露漏洞&#xff08;CVE-2017-12616&#xff09;、遠程代碼執行漏洞&#xff08;CVE-2017-12615&#xff09;&#xff0c;在某些場景下&#xff0c;攻…

2.0 STL泛型編程

Standard Template Library 在命名空間std中定義了常用的數據結構和算法 三種類型的組件&#xff1a; 容器&#xff1a; ——vector、string ——set、multiset、map、multimap ——list ——bitset ——stack ——deque、queue、priority_queue 迭代器 算法&…

SQL聯合更新

update CCTDB..Area_Infoset ParentStrb.ParentStrfrom CCTDB..Area_Info a inner join TempArea bon a.AreaId b.AreaId轉載于:https://www.cnblogs.com/davidgu/archive/2012/08/10/2631289.html

集合之ArrayList(含JDK1.8源碼分析)

一、ArrayList的數據結構 ArrayList底層的數據結構就是數組&#xff0c;數組元素類型為Object類型&#xff0c;即可以存放所有類型數據。我們對ArrayList類的實例的所有的操作(增刪改查等)&#xff0c;其底層都是基于數組的。 定義底層數據結構&#xff1a;Object[] elementDat…

2.2 string

字符數組的封裝 基本操作與vector很像&#xff0c;它們內部采用的都是數組結構 #include<string> 創建string對象&#xff1a; string s; 給string對象賦值&#xff1a; 方式一&#xff1a;s"i love coding"; 方式二&#xff1a; char a[256]; scanf(&qu…

Unity3D 自動打包整個項目(以AssetBundle實現)

需求&#xff1a; 在移動開發中&#xff0c;手動控制資源的加載、釋放和熱更新&#xff0c;是很有必要的。 而Unity通過AssetBundle可以實現該需求&#xff0c;但是如果項目資源多起來的話一個個手動打包成AssetBundle則很麻煩。 而本文正為此提供一套一鍵打包的方案。 資源分…

Android復制assets目錄下的圖片到內存

轉自&#xff1a;http://www.chenwg.com/android/android%E5%A4%8D%E5%88%B6assets%E7%9B%AE%E5%BD%95%E4%B8%8B%E7%9A%84%E5%9B%BE%E7%89%87%E5%88%B0%E5%86%85%E5%AD%98.html 有些Android應用需要一些初始化數據&#xff0c;但是考慮到國內這種龜速網絡和高昂的網絡流量費用&…

Python 2.7 cython cythonize py 編譯成 pyd 談談那些坑(轉載)

轉自&#xff1a;https://www.cnblogs.com/ibingshan/p/10334471.html Python 2.7 cython cythonize py 編譯成 pyd 談談那些坑 前言 基于 python27 的 pyc 很容易被反編譯&#xff0c;于是想到了pyd&#xff0c;加速運行&#xff0c;安全保護 必要準備 安裝cython&#xff1a;…

2.3 set

#include<set> 紅黑樹&#xff08;Red-Black Tree&#xff09;&#xff0c;一種平衡二叉檢索樹。 對于插入相同鍵值的情況忽略處理。 set主要用于快速檢索 高效的插入和刪除 multiset、map、multimap都是平衡二叉檢索樹。 創建set集合&#xff1a; set<int> s…

一、創建Assetbundle 在unity3d開發的游戲中,無論模型,音頻,還是圖片等,我們都做成Prefab,然后打包成Assetbundle,方便我們后面的使用,來達到資源的更新。

一、創建Assetbundle 在unity3d開發的游戲中&#xff0c;無論模型&#xff0c;音頻&#xff0c;還是圖片等&#xff0c;我們都做成Prefab&#xff0c;然后打包成Assetbundle&#xff0c;方便我們后面的使用&#xff0c;來達到資源的更新。 一個Assetbundle可以打包一個模型&…

【JS】我的JavaScript學習之路(2)

3.從JavaScript頁面解析過程看執行順序 代碼(test.html)&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/x…

Codeforces 862D. Mahmoud and Ehab and the binary string 【二分】(交互)

<題目鏈接> 題目大意&#xff1a; 有一個長度為n(n<1000)的01串&#xff0c;該串中至少有一個0和一個1&#xff0c;現在由你構造出一些01串&#xff0c;進行詢問&#xff0c;然后系統會給出你構造的串與原串的 Hamming distance &#xff0c;現在要求你按照步驟進行…

王者榮耀提取攻略

1. 王者榮耀安裝后&#xff0c;就將模型等資源解壓到SD卡目錄里&#xff0c;我們需要找到這個目錄。模型資源存儲在SD卡中&#xff0c;路徑為&#xff1a;【/SDCard/Android/data/com.tencent.tmgp.sgame/files/Resources/AssetBundle/】 2. 2 所有英雄的資源包都在這個目…

2.4 multiset

#include<set> multiset與set的唯一不同&#xff1a;允許插入重復的元素。 在插入元素、刪除元素、查找元素上與set 有區別。 multiset元素的插入&#xff1a; multiset<int> ms; ms.insert(11); ms.insert(11); //插入兩個11&#xff0c;遍歷時同樣有兩個11。…

Exchange ActiveSyn身份驗證類型

http://www.exchangecn.com/html/exchange2010/20110125_316.html 配置 Exchange ActiveSync 身份驗證 時間:2011-01-25 11:01來源:Exchange中文站 作者:Exchange中文站 點擊:3045次ActiveSync 身份驗證是客戶端和服務器驗證其身份以進行數據傳輸的過程&#xff0c;本文以示例的…

HotSpot 虛擬機垃圾回收算法實現

作為使用范圍最廣的虛擬機之一HotSpot&#xff0c;必須對垃圾回收算法的執行效率有嚴格的考量&#xff0c;只有這樣才能保證虛擬機高效運行 枚舉根節點 從可達性分析中從 GC Roots 節點找引用鏈這個操作為例&#xff0c;可以作為 GC Roots 的節點主要在全局性的引用&#xff08…