模擬便可node
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N; string s,tar = "AKIHABARA"; bool Solve() { cin >> s; if(s.length() > 9) { return false; } for(int i = 0 ; i < 9 ; ++i) { if(s.length() <= i) s += "A"; if(s[i] != tar[i]) { if(tar[i] == 'A') { s.insert(i,1,'A'); } else return false; } } if(s != tar) return false; return true; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif if(Solve()) puts("YES"); else puts("NO"); return 0; }
abc出現次數的最大值和最小值相差不超過1c++
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } char s[MAXN]; int cnt[4]; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif scanf("%s",s + 1); int N = strlen(s + 1); for(int i = 1 ; i <= N ; ++i) { cnt[s[i] - 'a']++; } int minn = min(min(cnt[0],cnt[1]),cnt[2]); int mmax = max(max(cnt[0],cnt[1]),cnt[2]); if(mmax - minn <= 1) puts("YES"); else puts("NO"); return 0; }
顯然每一個時間有超過三我的答案必定是0
以後對於每一個時間裏的人進行枚舉是d仍是24 - d便可優化
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int cnt[15]; int N,D[55]; bool vis[25],mark[15],c[25]; void Init() { read(N); for(int i = 1 ; i <= N ; ++i) {read(D[i]);cnt[D[i]]++;} } void Solve() { if(cnt[0] || cnt[12] >= 2) {puts("0");return;} int S = 0; int ans = 0,d = 12; for(int i = 1 ; i <= 12 ; ++i) { if(cnt[i] > 2) {puts("0");return;} if(cnt[i] == 2) { vis[i] = 1;vis[24 - i] = 1; } else if(cnt[i]) {d = min(d,i);S |= 1 << i - 1;mark[i] = 1;} } for(int T = S ; ; T = S & (T - 1)) { memcpy(c,vis,sizeof(vis)); for(int i = 1 ; i <= 12 ; ++i) { if(mark[i]) { if(T >> (i - 1) & 1) c[24 - i] = 1; else c[i] = 1; } } int pre = 0,t = d; for(int i = 1 ; i <= 24 ; ++i) { if(c[i]) {t = min(t,i - pre);pre = i;} } ans = max(ans,t); if(T == 0) break; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }
若是兩個相鄰的點\(a\)和\(b\),前面的前綴和是\(x\)
那麼咱們有
\(min(H[a],H[b] - P[a]) >= x\)
\(min(H[b],H[a] - P[b]) >= x\)
咱們但願容許儘可能寬鬆的x
若是\(min(H[a],H[b] - P[a]) < min(H[b],H[a] - P[b])\)的話,a在前,不然b在前ui
排序後進行\(dp[i][j]\)表示到第\(i\)個點選了\(j\)個點最小前綴和便可,用前綴min優化更新spa
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 5005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int H[MAXN],P[MAXN],id[MAXN],N; int64 sum[MAXN]; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(H[i]);read(P[i]);id[i] = i; } sort(id + 1,id + N + 1,[](int a,int b) { if(H[a] < H[b] - P[a]) return true; if(H[b] < H[a] - P[b]) return false; return H[a] + P[a] < H[b] + P[b]; }); for(int i = 1 ; i <= N ; ++i) sum[i] = 1e18; for(int i = 1 ; i <= N ; ++i) { int u = id[i]; for(int j = N ; j >= 1 ; --j) { if(H[u] >= sum[j - 1]) { sum[j] = min(sum[j],sum[j - 1] + P[u]); } } } for(int i = N ; i >= 1 ; --i) { if(sum[i] != 1e18) {out(i);enter;return;} } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
處理成差分,對稱位置的差分和爲0
例如abcba
能夠獲得的差分是
至關於數列
0123210
111-1-1-1code
而有區間加呢,至關於在前面打了一個+1,後面打了一個-1
咱們把這兩個位置連邊
而且給全部對稱位置連邊排序
合法的狀況僅當一個聯通塊和爲0ci
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } char s[MAXN]; int a[MAXN],N,M; struct node { int to,next; }E[MAXN * 10]; int head[MAXN],sumE,sum; bool vis[MAXN]; void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } void Init() { scanf("%s",s + 1); N = strlen(s + 1); s[0] = 'a';s[N + 1] = 'a'; for(int i = 1 ; i <= N + 1; ++i) a[i] = (s[i] - s[i - 1] + 26) % 26; read(M); int L,R; for(int i = 1 ; i <= M ; ++i) { read(L);read(R); add(L,R + 1);add(R + 1,L); } for(int i = 1 ; i <= N + 1 ; ++i) { add(i,N + 2 - i); } } void dfs(int u) { vis[u] = 1; sum = (sum + a[u]) % 26; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v]) { dfs(v); } } } void Solve() { bool flag = 1; for(int i = 1 ; i <= N + 1 ; ++i) { if(!vis[i]) { sum = 0; dfs(i); if(sum != 0) {flag = 0;break;} } } if(flag) puts("YES"); else puts("NO"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }
給第一行填上1 - K,很容易發現N的下界是\(K(K - 1) + 1\)
而後給第2到\(K\)行全填上1,\(K + 1\)到\(2K\)全填上2,以此類推
而後咱們再把剩餘未分配的數全填到\(2\)行到\(K\)行大小爲\(K - 1\)的正方形矩陣裏
而後咱們要把這個正方形矩陣劃分紅\(K - 1\)種,每種\(K - 1\)條不相交的鏈
把\(K - 1\)選一個質數能夠完成這個操做get
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 5005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } vector<int> v[1500]; int N = 1407; int K = 38; int a[45][45]; void Solve() { for(int i = 1 ; i <= K ; ++i) v[1].pb(i); int t = 0; for(int i = 2 ; i <= N ; i += (K - 1)) { ++t; for(int j = i ; j <= i + (K - 1) - 1 ; ++j) v[j].pb(t); } t = K; for(int i = 0 ; i < K - 1 ; ++i) { for(int j = 0 ; j < K - 1 ; ++j) { a[i][j] = ++t; v[i + 2].pb(t); } } t = 0; for(int i = K + 1 ; i <= N ; i += (K - 1)) { for(int j = 0 ; j < K - 1 ; ++j) { int p = j; for(int h = 0 ; h < K - 1 ; ++h) { v[i + j].pb(a[h][p]); p = (p + t) % (K - 1); } } ++t; } out(N);space;out(K);enter; for(int i = 1 ; i <= N ; ++i) { for(auto b : v[i]) { out(b);space; } enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
很容易想到\(sum[i][j]\)表示第\(i\)個點還須要後面給加\(j\)次的價值總和,\(cnt[i][j]\)表示第\(i\)個點還須要後面給加\(j\)次的方案數string
因爲能用到的狀態很少,能夠記憶化搜索,答案是\(dp[N][0]\)
轉移就枚舉這第\(i\)位放了\(p\)個,須要後面加\(d\)個
簡單列個方程能夠知道後面須要加\(d + \lfloor \frac{d + p}{i} \rfloor\)
而後加上\(cnt[i - 1][d + \lfloor \frac{d + p}{i} \rfloor] * (p - \frac{d + p}{i})\)
邊界是對於1,\(sum[1][d] = \frac{(K - 1) * (K + 2)}{2} - 2 * d,cnt[1][d] = K + 1\)
由於1若是不滿的話加多少都會扔掉
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; bool vis[105][100005]; int sum[105][100005],cnt[105][100005]; int N,K; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void update(int &x,int y) { x = inc(x,y); } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void dfs(int p,int d) { if(vis[p][d]) return; vis[p][d] = 1; if(p == 1) { cnt[p][d] = K + 1;sum[p][d] = (mul(2,MOD - d) + (K + 2) * (K - 1) / 2) % MOD; return ; } for(int i = 0 ; i < p ; ++i) { if(i > K) break; dfs(p - 1,d + (d + i) / p); update(cnt[p][d],cnt[p - 1][d + (d + i) / p]); update(sum[p][d],inc(sum[p - 1][d + (d + i) / p] ,mul(cnt[p - 1][d + (d + i) / p] ,inc(i, MOD - (d + i) / p)))); } if(p <= K) { dfs(p - 1,d + 1 + d / p); update(cnt[p][d],cnt[p - 1][d + 1 + d / p]); update(sum[p][d],inc(sum[p - 1][d + 1 + d / p], mul(cnt[p - 1][d + 1 + d / p],inc(p, MOD - d / p - 1)))); } for(int i = p + 1 ; i <= K ; ++i) { dfs(p - 1,d); update(cnt[p][d],cnt[p - 1][d]); update(sum[p][d],inc(sum[p - 1][d],mul(cnt[p - 1][d], i))); } } void Solve() { read(N);read(K); dfs(N,0); out(sum[N][0]);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
題解裏的圖畫的挺好的
就是咱們考慮把大矩形分紅小矩形的代價是什麼
例如一個矩形\([lx,ly,rx,ry]\)
我把它從\([lx,ly,i,j]\)裏分出來
須要就是把
\([lx,ry + 1,rx,j]\)和\([rx + 1,ly,i,ry]\)裏全部的障礙都扣去
而後咱們對於每一個包含p點的矩形,計算使得從P開始左上右上左下右下的一個角都扣去的最小代價
其實這是\(n^6\)的,慫的一批,不過記憶化搜索加上一點剪枝和AtCoder強大的評測機,好像仍是不到1s的樣子
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } bool vis[45][45][45][45]; int dp[45][45][45][45]; char s[45][45]; int H,W,sum[45][45]; void Init() { read(H);read(W); for(int i = 1 ; i <= H ; ++i) scanf("%s",s[i] + 1); } int query(int lx,int ly,int rx,int ry) { return sum[rx][ry] + sum[lx - 1][ly - 1] - sum[rx][ly - 1] - sum[lx - 1][ry]; } int dfs(int lx,int ly,int rx,int ry) { if(lx == 1 && ly == 1 && rx == H && ry == W) return 0; if(vis[lx][ly][rx][ry]) return dp[lx][ly][rx][ry]; int res = 100000; for(int i = rx + 1 ; i <= H ; ++i) { for(int j = ry + 1 ; j <= W ; ++j) { int t = query(lx,ry + 1,rx,j) + query(rx + 1,ly,i,ry); if(t >= res) break; res = min(t + dfs(lx,ly,i,j),res); } } for(int i = rx + 1 ; i <= H ; ++i) { for(int j = ly - 1 ; j >= 1 ; --j) { int t = query(lx,j,rx,ly - 1) + query(rx + 1,ly,i,ry); if(t >= res) break; res = min(t + dfs(lx,j,i,ry),res); } } for(int i = lx - 1 ; i >= 1 ; --i) { for(int j = ly - 1 ; j >= 1 ; --j) { int t = query(i,ly,lx - 1,ry) + query(lx,j,rx,ly - 1); if(t >= res) break; res = min(t + dfs(i,j,rx,ry),res); } } for(int i = lx - 1 ; i >= 1 ; --i) { for(int j = ry + 1 ; j <= W ; ++j) { int t = query(i,ly,lx - 1,ry) + query(lx,ry + 1,rx,j); if(t >= res) break; res = min(t + dfs(i,ly,rx,j),res); } } vis[lx][ly][rx][ry] = 1; return dp[lx][ly][rx][ry] = res; } void Solve() { pii p; for(int i = 1 ; i <= H ; ++i) { for(int j = 1 ; j <= W ; ++j) { if(s[i][j] == 'P') p = mp(i,j); if(s[i][j] == '#') sum[i][j]++; sum[i][j] = sum[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]; } } int ans = 100000; for(int i = 1 ; i <= H ; ++i) { for(int j = 1 ; j <= W ; ++j) { for(int k = i ; k <= H ; ++k) { for(int h = j ; h <= W ; ++h) { if(p.fi >= i && p.fi <= k && p.se >= j && p.se <= h) { int t = query(i,j,p.fi,p.se); t = min(t,query(p.fi,p.se,k,h)); t = min(t,query(i,p.se,p.fi,h)); t = min(t,query(p.fi,j,k,p.se)); if(t >= ans) continue; ans = min(t + dfs(i,j,k,h),ans); } } } } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }
觀察一下可得
\(a_{i} < a_{i | 2^{k}}\)
咱們把這個當作一條邊,會連出一個dag,至關於給出拓撲序的一部分回覆所有
能夠對每一個點求一個放的位置取值範圍,若是這個點固定了就把左右端點都設成那個值
而後每次選一個右端點最小的放進去,不存在或右端點不合法就是無解了
恢復成原來的觀察一下就是二進制反轉
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int A[(1 << 18) + 5],N; vector<int> e[2][(1 << 18) + 5]; int d[2][(1 << 18) + 5]; int L[(1 << 18) + 5],R[(1 << 18) + 5]; int que[2][(1 << 18) + 5],ql,qr,ans[(1 << 18) + 5]; vector<int> st[(1 << 18) + 5],ed[(1 << 18) + 5]; struct cmp { bool operator () (const int &a,const int &b) const { return R[a] < R[b] || (R[a] == R[b] && a < b); } }; set<int,cmp> S; void Init() { read(N); for(int i = 0 ; i < (1 << N) ; ++i) { read(A[i]);--A[i]; for(int j = 0 ; j < N ; ++j) { if(!(i >> j & 1)) { e[0][i].pb(i + (1 << j)); d[0][i + (1 << j)]++; e[1][i + (1 << j)].pb(i); d[1][i]++; } } L[i] = 0;R[i] = (1 << N) - 1; } } void Solve() { L[0] = R[0] = 0; for(int i = 0 ; i < (1 << N) ; ++i) { if(A[i] != -1) L[i] = A[i]; int u = i; for(auto v : e[0][u]) { L[v] = max(L[v],L[u] + 1); } } R[(1 << N) - 1] = L[(1 << N) - 1] = (1 << N) - 1; for(int i = (1 << N) - 1 ; i >= 0 ; --i) { if(A[i] != -1) R[i] = A[i]; int u = i; for(auto v : e[1][u]) { R[v] = min(R[u] - 1,R[v]); } } for(int i = 0 ; i < (1 << N) ; ++i) { st[L[i]].pb(i); } for(int i = 0 ; i < (1 << N) ; ++i) { for(auto t : st[i]) S.insert(t); if(S.empty()) {puts("NO");return;} int t = *S.begin(); S.erase(S.begin()); if(R[t] < i) {puts("NO");return;} ans[t] = i; } puts("YES"); for(int i = 1 , j = (1 << N - 1) ; i < (1 << N) - 1 ; ++i) { if(i < j) swap(ans[i],ans[j]); int k = (1 << N - 1); while(j >= k) { j -= k; k >>= 1; } j += k; } for(int i = 0 ; i < (1 << N) ; ++i) { out(ans[i] + 1);space; } enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }
好像直接點分能夠爆艹
就是考慮點分每一個點向別的子樹裏距離最短的點連邊便可
而後直接kruskal
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N; int64 X[MAXN]; struct node { int to,next;int64 val; }E[MAXN * 2]; int head[MAXN],sumE; int que[MAXN],ql,qr,fa[MAXN],siz[MAXN],son[MAXN]; int64 dis[MAXN]; pair<int64,int> pre[MAXN],suf[MAXN]; vector<int> ver[MAXN]; bool vis[MAXN]; struct Enode { int u,v;int64 c; friend bool operator < (const Enode &a,const Enode &b) { return a.c < b.c; } }edge[MAXN * 30]; int tot; void add(int u,int v,int64 c) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].val = c; head[u] = sumE; } void Init() { read(N); for(int i = 1 ; i <= N ; ++i) read(X[i]); int a,b;int64 c; for(int i = 1 ; i < N ; ++i) { read(a);read(b);read(c); add(a,b,c);add(b,a,c); } } int getfa(int u) { return fa[u] == u ? u : fa[u] = getfa(fa[u]); } int Calc(int st) { que[ql = qr = 1] = st; fa[st] = 0;dis[st] = 0; while(ql <= qr) { int u = que[ql++]; siz[u] = 1;son[u] = 0; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u] && !vis[v]) { que[++qr] = v; fa[v] = u; } } } int res = que[qr]; for(int i = qr ; i >= 1 ; --i) { int u = que[i]; if(fa[u]) {son[fa[u]] = max(son[fa[u]],siz[u]);siz[fa[u]] += siz[u];} son[u] = max(son[u],qr - siz[u]); if(son[u] < son[res]) res = u; } return res; } void dfs(int u) { int G = Calc(u); vis[G] = 1; int cnt = 0; dis[G] = 0; for(int i = head[G] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v]) { ++cnt; ver[cnt].clear(); ver[cnt].pb(v); fa[v] = G;dis[v] = dis[G] + E[i].val; int s = 0;pair<int64,int> val = mp(dis[v] + X[v],v); while(s < ver[cnt].size()) { int n = ver[cnt][s];++s; for(int k = head[n] ; k ; k = E[k].next) { int h = E[k].to; if(!vis[h] && h != fa[n]) { fa[h] = n; ver[cnt].pb(h); dis[h] = dis[n] + E[k].val; val = min(mp(dis[h] + X[h],h),val); } } } pre[cnt] = val; suf[cnt] = val; } } pre[0] = mp(1e18,0); for(int i = 1 ; i <= cnt ; ++i) pre[i] = min(pre[i - 1],pre[i]); suf[cnt + 1] = mp(1e18,0); for(int i = cnt ; i >= 1 ; --i) suf[i] = min(suf[i + 1],suf[i]); for(int i = 1 ; i <= cnt ; ++i) { pair<int64,int> t = min(pre[i - 1],suf[i + 1]); t = min(t,mp(X[G],G)); for(auto v : ver[i]) { edge[++tot] = (Enode){v,t.se,t.fi + dis[v] + X[v]}; } } edge[++tot] = (Enode){G,pre[cnt].se,pre[cnt].fi + dis[G] + X[G]}; for(int i = head[G] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v]) dfs(v); } } void Solve() { dfs(1); sort(edge + 1,edge + tot + 1); for(int i = 1 ; i <= N ; ++i) fa[i] = i; int64 ans = 0; int cnt = 0; for(int i = 1 ; i <= tot ; ++i) { if(getfa(edge[i].u) != getfa(edge[i].v)) { ans += edge[i].c; fa[getfa(edge[i].u)] = getfa(edge[i].v); ++cnt; if(cnt == N - 1) break; } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }