国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[BZOJ3697]采藥人的路徑(點分治)

2019-11-08 19:48:20
字體:
來源:轉載
供稿:網友

題目描述

傳送門

題解

點分治裸題(笑 黃學長的題解看不懂啊。。。 自己yy了一種做法 果然蠢到爆炸

將邊權看成1和-1,那么合法的路徑即為路徑權值和為0,并且從中間分開兩段和都是0 如果從路徑的一個起點開始做前綴和的話,要求終點的權為0且中間點的權出現過0 進行點分治,每一次對所有的點做以當前根為起點的前綴和,然后每一個點都得到了一個點權 要將這些點兩兩組合使得整條路徑合法 首先顯然如果兩個點權相加為0才是合法的匹配 如果當前點到根的路徑中存在點和這個點的點權相等,那么這條路徑已經單獨存在休息站,將這個點標記 然后分類討論 如果當前點權為0,如果沒有標記,那么可以和其它任意的0匹配;如果有標記,那么不光可以和其它任意的0匹配,還可以自己到根算一條路徑 如果當前點權不為0且沒有標記,那么只能和有標記的匹配 如果當前點權不為0且有標記,那么可以和其它任意合法的匹配 用數組記錄權為i的個數然后計算就行了 時間復雜度O(nlogn?一坨常數)

代碼

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define LL long long#define N 100005#define base 100000int n,x,y,z,sum,root,cs,cn;int tot,point[N],nxt[N*2],v[N*2],c[N*2];int size[N],big[N],d[N],nph[N];int cnt[N*2],soncnt[N*2],nphcnt[N*2];struct data{int sum,x;bool flag;}son[N];bool vis[N];LL ans;void add(int x,int y,int z){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;}void getroot(int x,int fa){ size[x]=1;big[x]=0; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa&&!vis[v[i]]) { getroot(v[i],x); size[x]+=size[v[i]]; big[x]=max(big[x],size[v[i]]); } big[x]=max(big[x],sum-size[x]); if (big[x]<big[root]) root=x;}void getdeep(int x,int fa){ for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa&&!vis[v[i]]) { d[v[i]]=d[x]+c[i]; son[++cs].sum=d[v[i]]; son[cs].x=v[i]; if (cnt[d[v[i]]+base]) { son[cs].flag=1; nph[++cn]=d[v[i]]; } else son[cs].flag=0; ++cnt[d[v[i]]+base]; getdeep(v[i],x); --cnt[d[v[i]]+base]; }}LL calc(int x,int now){ d[x]=now; cs=cn=0; if (now) { son[++cs].sum=now,son[cs].flag=0; son[cs].x=x; ++cnt[now+base]; } getdeep(x,0); if (now) --cnt[now+base]; for (int i=1;i<=cs;++i) ++soncnt[son[i].sum+base]; for (int i=1;i<=cn;++i) ++nphcnt[nph[i]+base]; LL t=0LL,count0=0LL,alone=0LL; for (int i=1;i<=cs;++i) { if (son[i].sum==0) { ++count0; if (son[i].flag) ++alone; continue; } if (son[i].flag==1) t+=(LL)soncnt[-son[i].sum+base]; else t+=(LL)nphcnt[-son[i].sum+base]; } for (int i=1;i<=cs;++i) --soncnt[son[i].sum+base]; for (int i=1;i<=cn;++i) --nphcnt[nph[i]+base]; LL re; if (!now) re=t/2LL+count0*(count0-1LL)/2LL+alone; else re=t/2LL+count0*(count0-1LL)/2LL; return re;}void dfs(int x){ ans+=calc(x,0); vis[x]=1; for (int i=point[x];i;i=nxt[i]) if (!vis[v[i]]) { ans-=calc(v[i],c[i]); sum=size[v[i]];root=0; getroot(v[i],0); dfs(root); }}int main(){ scanf("%d",&n); for (int i=1;i<n;++i) { scanf("%d%d%d",&x,&y,&z); if (!z) z=-1; add(x,y,z),add(y,x,z); } big[0]=N; sum=n;root=0; getroot(1,0); dfs(root);
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 封丘县| 达日县| 扎赉特旗| 江安县| 屏山县| 读书| 蚌埠市| 张掖市| 茶陵县| 安岳县| 武定县| 封丘县| 全南县| 图片| 嘉鱼县| 古交市| 宝应县| 凤冈县| 南涧| 兴和县| 乌鲁木齐县| 兴隆县| 平山县| 江川县| 浪卡子县| 江西省| 读书| 隆昌县| 嵊州市| 陇西县| 东乌珠穆沁旗| 中山市| 日喀则市| 宁国市| 化德县| 佛教| 安康市| 蒙城县| 德庆县| 凌云县| 西乌珠穆沁旗|