1. 程式人生 > >2018.09.30【Atcoder Regular Contest103】F

2018.09.30【Atcoder Regular Contest103】F

傳送門

解析:

本次構造題大賽的最後一道。
真的毒瘤啊,前面給一個那麼扯的DD,後面又給一個這麼神仙的結論題。

思路:

首先拿到題我整個人是方的,根本不知道如何下手。。。
找重心?明顯假了啊。。。

到所有點距離和最小的節點?似乎沒什麼好用的性質。

到所有點距離和最大的節點?一定是一個葉子!

考慮它不是一個葉子的情況,我們一定可以將它向葉子方向移動,從而得到一個更大的距離和。

那麼我們考慮怎麼找這個葉子的父親。
滿足Dw=Dv(n2)D_w=D_v-(n-2)的是這個葉子節點的父親。
考慮將該葉子節點向上挪一個單位的距離則新的節點到其他節點的距離各減少1,而這兩個節點之間的距離仍然是1

1,所以我們這樣就找到了它的父親。

為了便於敘述,我們不失一般性地定義D1<D2<<DND_1 < D_2 < · · · < D_N
並且將這棵樹定義為以11為根節點的有根樹。

我們採用倒敘列舉,對每個節點(除根節點)確定它的父親。

那麼接下來才是真正的結論:
從樹上移走一條邊<u,v><u,v>得到兩個聯通分量大小定義為nu,nvn_u,n_vDu,DvD_u,D_v

有如下關係Du+nu=Dv+nvD_u+n_u=D_v+n_v

證明很簡單,考慮將uuvv移動一個單位,那麼它離nvn_v中的所有節點近一個單位,離nun_u中所有節點遠一個單位。

那麼我們將上面這個式子變形Du=Dv+nvnu=Dv+N2×nuD_u=D_v+n_v-n_u=D_v+N-2\times n_u

那麼我們就可以通過由下向上的遞推來確定每一個uu的父親vv了。
中間判斷一下會不會出現父親的子樹大小小於兒子,非根節點沒有父親這兩種情況就行了。

最後再判斷一下根節點的距離限制是否滿足。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
ll getint(){
	re ll num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

inline
void outint(int a){
	static char ch[13];
	if(a==0)pc('0');
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

cs int N=100005;

int last[N],nxt[N],to[N],ecnt;
inline
void addedge(int u,int v){
	nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v;
}

map<ll,int> id;
int n;
ll d[N];
int siz[N];

int dist[N];
inline
void dfs(int u){
	for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
		dist[v]=dist[u]+1;
		dfs(v);
	}
}

vector<pair<int,int> > edge;

signed main(){
	n=getint();
	for(int re i=1;i<=n;++i)d[i]=getint(),id[d[i]]=i;
	
	sort(d+1,d+n+1);
	for(int re i=1;i<=n;++i)siz[i]=1;
	
	for(int re i=n;i>1;--i){
		int u=id[d[i]];
		int tmp=n-2*siz[u];
		if(tmp<=0)return puts("-1"),0; 
		ll t=d[i]-tmp;
		if(id.count(t)==0)return puts("-1"),0;
		int pos=id[t];
		addedge(pos,u);
		siz[pos]+=siz[u];
		edge.push_back(make_pair(pos,u));
	}
	ll sum=0;
	dfs(id[d[1]]);
	for(int re i=1;i<=n;++i){
		sum+=dist[i];
	}
	if(sum!=d[1])return puts("-1"),0;
	for(int re i=0;i<edge.size();++i)outint(edge[i].first),pc(' '),outint(edge[i].second),pc('\n');
	return 0;
}

相關推薦

2018.09.30Atcoder Regular Contest103F

傳送門 解析: 本次構造題大賽的最後一道。 真的毒瘤啊,前面給一個那麼扯的DDD題,後面又給一個這麼神仙的結論題。 思路: 首先拿到題我整個人是方的,根本不知道如何下手。。。 找重心?明顯假了啊。。。 到所有點距離和最小的節點?似乎沒什麼好用的性質。 到所有點

2018.09.29Atcoder Regular Contest 103E

傳送門 解析: 短程式碼神題。如果把我打比賽習慣的標頭檔案去掉,真的是非常短的程式碼量了。 然而這道題並不是如此簡單好想。 思路: 首先一棵樹必然有葉子節點,也就是說s[1]s[1]s[1]必須為111,因為我們必然會有一刀能夠切斷該葉子節點的與其父親的辦法。

2018.09.30LOJ517「LibreOJ β Round #2」計算幾何瞎暴力(01Trie)(二進位制拆分)

傳送門 解析: 看到標題的dalaodalaodalao先不要急著錘我。。。 這道題的二進位制拆分和01Trie01Trie01Trie不能混在一起,不要急著說01Trie01Trie01Trie就是二進位制拆分。。。 思路: 這道題可以說是非常好的一道資料結

2018.09.30POJ3348Cows(凸包)(三角剖分)

傳送門 解析: 讀優沒有寫負數又被卡了半個小時。。。 這裡採用JarrisJarrisJarris步進法求凸包。。主要講一講怎麼求多邊形面積。 思路: 滿足題意的顯然是這些點的凸包,而我們要做的就是求出凸包面積。 那麼怎麼求多邊形面積? 考慮三角剖分,我們將多

2018.09.29洛谷P2106Sam數(數位DP)(矩陣快速冪)

傳送門 解析: 其實這種只用位數轉移的數位DPDPDP,大概都可以用矩陣快速冪推。本質原因是每層的轉移方程與這是第幾層無關,比如這道題。 思路: 可以發現一個很顯然的情況,就是上面說的,這道題可以矩陣

2018.12.30NOIP提高組模擬A組 JZOJ 5354 導彈攔截

大意 三維導彈攔截 思路 對於最多幹掉的導彈數,由於導彈同時發射的,所以我們可以排序,然後 O (

2018.12.30NOIP提高組模擬賽C組總結

2018.12.30【NOIP提高組】模擬賽C組總結 今天成功迴歸開始做比賽 感覺十分良(zhōng)好(chà)。 統計數字(count.pas/c/cpp) 字串的展開(expand.pas/c/cpp) 矩陣取數遊戲(game.pas/c/cpp)

2018.3.28 AtCoder beginner092-C 解題報告(線性處理)

C - Traveling PlanTime limit : 2sec / Memory limit : 256MBScore : 300 pointsProblem StatementThere are N sightseeing spots on the x-axis,

2018.09.15校內模擬點名器(DP)

【題意】 ssoier在緊張的學習中,杜老師每天給他們傳授精妙的知識。 杜老師為了活躍氣氛,設計了一個點名器,這個點名器包含一個長度為M的陣列(下標1開始),每個元素是一個oier的名字,每次點名的

2018.09.22JSOI2008BZOJ1016最小生成樹計數(矩陣樹定理)(並查集)

傳送門 解析: 好的這是一道需要數學推理的矩陣樹題目。 首先我們考慮一個問題。 前置定理 我們先隨便做一棵最小生成樹。 重要定理:那麼在這棵生成樹中如果權值為www的邊有ttt條,那麼在所有最小生成樹中,權值為www的邊都有kkk條。 證明如下: 考慮在這棵

2018.09.26TJOI2017BZOJ4888洛谷P3760異或和(樹狀陣列)(差分)

洛谷傳送門 解析: 額,TJOITJOITJOI連續兩年考了位運算。。。 我還能說什麼。。。 PS:zxyoiPS:zxyoiPS:zxyoi不是天津oieroieroier。 思路: 一般位運算都

2018.09.26BZOJ4260Codechef REBXOR(01Trie)

傳送門 解析: 這種要求分成兩段的問題,一般就是處理出一個字首最大和一個字尾最大。 然後O(n)O(n)O(n)掃一遍就好了。 那麼,怎麼求? 這種異或問題當然還是要01Trie01Trie01Tri

2018.09.26BZOJ4602洛谷P4079SDOI2016齒輪(搜尋)(圖的遍歷)

洛谷傳送門 解析: 這道題O(V+E)O(V+E)O(V+E)就過了啊。。。 然而官方標解是並查集。。。 我。。。 思路: 只要按照圖的遍歷一邊跑一遍驗證就行了。 DFSDFSDFS比較好寫。 程

2018.12.30NOIP訓練SCOI2018Numazu 的蜜柑(二次剩餘)

題面傳送門 解析: 直接解方程可以得到 a u

2018.12.30國家集訓隊洛谷P1903數顏色 / 維護佇列(帶修莫隊)

傳送門 解析: 這道題好像以前在BZOJ上做過。 但是因為BZOJ資料較水,所以被我複雜度不對的程式碼搞過去了。。 真正的排序策略應該是這樣的: 塊大小設定成 n

2018.09.29BZOJ1026洛谷P2657SCOI2009windy數(數位DP)

洛谷傳送門 解析: 由於資料範圍很小(相對於大部分數位DPDPDP題來說)。 我們只記錄當前位,當前位數字,是否是前導0,是否達到上界。 簡單DP記憶化搜尋一下就好了。 程式碼: #include

2018.09.27BZOJ5221偏題(矩陣快速冪)(數學推理)

【問題描述】 斐波那契數列是一個經典遞推數列,即Fibn=Fibn−1+Fibn−2Fib_n=Fib_{n-1}+Fib_{n-2}Fibn​=Fibn−1​+Fibn−2​ 在這個問題中,定義一個新數列,對於n≥2n ≥ 2n≥2有Fn=Fn−1+Fn−2+

2018.09.28Vijos1053Easy sssp(SPFA判負環)

傳送門 解析: 深入理解SPFASPFASPFA的本質。 思路: 由於是佇列優化的Bellman−FordBellman-FordBellman−Ford,SPFASPFASPFA也具有判負環的功能,

2018.09.29HDU2089不要62(數位DP)

傳送門 解析: 今天突然發現自己還沒寫過數位DPDPDP入門題。。。 思路: 我們從高位向低位DP,採用記憶化搜尋。 初始化fff陣列為−1-1−1,因為我們可能DPDPDP到某個狀態是沒有合法數的。