#include
template <class T>
inline void read(T &res)
{
char ch; bool flag = false; res = 0;
while (ch = getchar(), !isdigit(ch) && ch != '-');
ch == '-' ? flag = true : res = ch ^ 48;
while (ch = getchar(), isdigit(ch))
res = res * 10 + ch - 48;
flag ? res = -res : 0;
}
typedef long long ll;
typedef long double ld;
const ld Maxn = 4e18;
const int N = 2e5 + 5;
int n, tn;
template <class T>
inline T Min(T x, T y) {return x < y ? x : y;}
template <class T>
inline void CkMin(T &x, T y) {x > y ? x = y : 0;}
template <class T>
inline T Abs(T x) {return x < 0 ? -x : x;}
struct point
{
int x, y;
point() {}
point(int X, int Y):
x(X), y(Y) {}
inline ld dist()
{
return sqrt((ld)x * x + (ld)y * y);
}
inline void scan()
{
read(x);
read(y);
}
inline point operator - (const point &a) const
{
return point(x - a.x, y - a.y);
}
}p[N], t[N];
inline bool cmpx(const point &a, const point &b)
{
return a.x < b.x || a.x == b.x && a.y < b.y;
}
inline bool cmpy(const point &a, const point &b)
{
return a.y < b.y || a.y == b.y && a.x < b.x;
}
inline ld solve(int l, int r)
{
if (l == r)
return Maxn;
int mid = l + r >> 1, xmid = p[mid].x;
ld dist = Min(solve(l, mid), solve(mid + 1, r));
std::inplace_merge(p + l, p + mid + 1, p + r + 1, cmpy);
tn = 0;
for (int i = l; i <= r; ++i)
if (Abs(p[i].x - xmid) < dist)
{
for (int j = tn; j >= 1 && p[i].y - t[j].y < dist; --j)
CkMin(dist, (p[i] - t[j]).dist());
t[++tn] = p[i];
}
return dist;
}
int main()
{
read(n);
for (int i = 1; i <= n; ++i)
p[i].scan();
std::sort(p + 1, p + n + 1, cmpx);
printf("%.4lf\n", (double)solve(1, n));
}
nth_element 函数实现原理,可用类似快速排序的 Partition 函数求解该问题。inline int Rand(int l, int r)
{
return 1ll * rand() * rand() % (r - l) + l;
}
inline int Partition(int *a, int l, int r)
{
std::swap(a[l], a[Rand(l, r)]);
int pivot = a[l];
while (l < r)
{
while (l < r && a[r] >= pivot)
--r;
a[l] = a[r];
while (l < r && a[l] <= pivot)
++l;
a[r] = a[l];
}
a[l] = pivot;
return l;
}
inline void nthElement(int *a, int l, int r, int k)
{
if (l == r)
return ;
int pos = Partition(a, l, r);
int cnt = pos - l + 1;
if (k == cnt)
return ;
else if (k > cnt)
nthElement(a, pos + 1, r, k - cnt);
else
nthElement(a, l, pos - 1, k);
}
struct traceback
{
int *addr, val;
traceback() {}
traceback(int *Addr, int Val):
addr(Addr), val(Val) {}
}stk[L];
inline void Change(int &x, int v)
{
stk[++top] = traceback(&x, x);
x = v;
}
inline void Back(int _top)
{
while (top != _top)
{
*(stk[top].addr) = stk[top].val;
--top;
}
}
s u m i = ∑ j = 1 n s ( i , j ) sum_i = \sum \limits_{j = 1}^{n}s(i,j) sumi=j=1∑ns(i,j)
#include
using std::ios;
using std::cin;
using std::cout;
typedef long long ll;
const int Maxn = 1e9;
const int N = 1e5 + 5;
const int N2 = 2e5 + 5;
int n, m, Gsze, Gid, tot, top, apr_col, extra;
int sze[N], col[N], stk[N], cnt[N], csze[N];
ll tot_csze, sum[N]; bool vis[N];
struct arc
{
int to, cst;
arc *nxt;
}p[N2], *adj[N], *P = p;
inline void linkArc(int x, int y)
{
(++P)->nxt = adj[x]; adj[x] = P; P->to = y;
(++P)->nxt = adj[y]; adj[y] = P; P->to = x;
}
inline void CkMax(int &x, int y) {if (x < y) x = y;}
inline void dfsInit(int x, int fa)
{
int cnt = 0;
sze[x] = 1;
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (y == fa || vis[y])
continue;
dfsInit(y, x);
sze[x] += sze[y];
CkMax(cnt, sze[y]);
}
CkMax(cnt, tot - sze[x]);
if (cnt < Gsze)
Gsze = cnt, Gid = x;
}
inline int findG(int x)
{
Gsze = Maxn;
dfsInit(x, 0);
return Gid;
}
inline void addCol(int x, int t)
{
stk[++top] = x;
if (++cnt[col[x]] == 1)
{
csze[col[x]] += t * sze[x];
tot_csze += t * sze[x];
}
}
inline void delCol()
{
int x = stk[top--];
--cnt[col[x]];
}
inline void dfsCol1(int x, int Fa, int t)
{
addCol(x, t);
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y] || y == Fa)
continue ;
dfsCol1(y, x, t);
}
delCol();
}
inline void dfsCol2(int x, int Fa)
{
if (++cnt[col[x]] == 1)
{
tot_csze -= csze[col[x]];
++apr_col;
}
sum[x] += 1ll * apr_col * extra + tot_csze;
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (y == Fa || vis[y])
continue ;
dfsCol2(y, x);
}
if (--cnt[col[x]] == 0)
{
tot_csze += csze[col[x]];
--apr_col;
}
}
inline void dfsSze(int x, int Fa)
{
sze[x] = 1;
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y] || y == Fa)
continue ;
dfsSze(y, x);
sze[x] += sze[y];
}
}
inline void solve(int x)
{
x = findG(x);
dfsSze(x, 0); //注意求完重心后一定要重新求一遍 size,否则递归到子树时 tot 的计算是错误的
vis[x] = true;
addCol(x, 1);
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y])
continue ;
dfsCol1(y, x, 1);
}
sum[x] += tot_csze;
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y])
continue ;
dfsCol1(y, x, -1);
extra = tot - sze[y];
tot_csze -= csze[col[x]];
++apr_col;
dfsCol2(y, x);
--apr_col;
tot_csze += csze[col[x]];
dfsCol1(y, x, 1);
}
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y])
continue ;
dfsCol1(y, x, -1);
}
top = cnt[col[x]] = csze[col[x]] = tot_csze = 0;
for (arc *e = adj[x]; e; e = e->nxt)
{
int y = e->to;
if (vis[y])
continue ;
tot = sze[y];
solve(y);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> col[i];
for (int i = 1, x, y; i < n; ++i)
{
cin >> x >> y;
linkArc(x, y);
}
tot = n;
solve(1);
for (int i = 1; i <= n; ++i)
cout << sum[i] << '\n';
}
#include
using std::cin;
using std::cout;
using std::ios;
using std::priority_queue;
using std::vector;
const int N = 1e5 + 5;
const int Maxn = 1e9;
int col[N], sze[N], anc[N][20], tdep[N], dep[N], tanc[N], tdis[N][20];
int n, Q, rt, Gsze, Gid, tot;
vector<int> e[N]; bool vis[N];
template <class T>
inline void CkMax(T &x, T y) {x < y ? x = y : 0;}
struct delHeap //可删大根堆
{
priority_queue<int> a, b; //heap = a - b
inline void Push(int v) {a.push(v);}
inline void Erase(int v) {b.push(v);}
inline int Size() {return a.size() - b.size();}
inline void Pop()
{
while (!b.empty() && a.top() == b.top())
a.pop(), b.pop();
a.pop();
}
inline int Top()
{
while (!b.empty() && a.top() == b.top())
a.pop(), b.pop();
return a.top();
}
inline int Top2()
{
int x = Top();
a.pop();
int y = Top();
a.push(x);
return y;
}
}dist[N], ch[N], ans;
inline int queryLCA(int x, int y)
{
if (x == y)
return x;
if (dep[x] < dep[y])
std::swap(x, y);
for (int i = 18; i >= 0; --i)
{
if (dep[anc[x][i]] >= dep[y])
x = anc[x][i];
if (x == y)
return x;
}
for (int i = 18; i >= 0; --i)
if (anc[x][i] != anc[y][i])
x = anc[x][i], y = anc[y][i];
return anc[x][0];
}
inline int queryDis(int x, int y)
{
return dep[x] + dep[y] - (dep[queryLCA(x, y)] << 1);
}
inline void initLCA(int x)
{
dep[x] = dep[anc[x][0]] + 1;
for (int i = 0; anc[x][i]; ++i)
anc[x][i + 1] = anc[anc[x][i]][i];
for (int y : e[x])
{
if (y == anc[x][0])
continue ;
anc[y][0] = x;
initLCA(y);
}
}
inline void dfsInit(int x, int Fa)
{
int cnt = 0;
sze[x] = 1;
for (int y : e[x])
{
if (vis[y] || y == Fa)
continue;
dfsInit(y, x);
sze[x] += sze[y];
CkMax(cnt, sze[y]);
}
CkMax(cnt, tot - sze[x]);
if (cnt < Gsze)
Gsze = cnt, Gid = x;
}
inline void dfsSze(int x, int Fa, int rt, int d)
{
sze[x] = 1;
if (rt)
dist[rt].Push(tdep[x]);
tdep[x] = d;
for (int y : e[x])
{
if (vis[y] || y == Fa)
continue ;
dfsSze(y, x, rt, d + 1);
sze[x] += sze[y];
}
}
inline int findG(int x)
{
Gsze = Maxn;
dfsInit(x, 0);
return Gid;
}
inline void solve(int x, int Fa)
{
vis[x = findG(x)] = true;
tanc[x] = Fa;
dfsSze(x, 0, Fa ? x : 0, 0);
if (!Fa)
rt = x;
else
ch[Fa].Push(dist[x].Top());
ch[x].Push(0);
for (int y : e[x])
{
if (vis[y])
continue ;
tot = sze[y];
solve(y, x);
}
if (ch[x].Size() >= 2)
ans.Push(ch[x].Top() + ch[x].Top2());
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n;
for (int i = 1, u, v; i < n; ++i)
{
cin >> u >> v;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
initLCA(1);
tot = n;
solve(1, 0);
for (int x = 1; x <= n; ++x)
col[x] = 1;
for (int x = 1; x <= n; ++x)
for (int y = tanc[x], t = 0; y; y = tanc[y], ++t)
tdis[x][t] = queryDis(x, y);
char opt; int x, cnt = n;
cin >> Q;
while (Q--)
{
cin >> opt;
if (opt == 'C')
{
cin >> x;
int u = x;
if (ch[x].Size() >= 2)
ans.Erase(ch[x].Top() + ch[x].Top2());
if (col[u])
ch[x].Erase(0);
else
ch[x].Push(0);
if (ch[x].Size() >= 2)
ans.Push(ch[x].Top() + ch[x].Top2());
for (int y = tanc[x], t = 0; x; x = y, y = tanc[y], ++t)
{
if (y)
{
if (ch[y].Size() >= 2)
ans.Erase(ch[y].Top() + ch[y].Top2());
if (dist[x].Size())
ch[y].Erase(dist[x].Top());
}
if (col[u])
dist[x].Erase(tdis[u][t]);
else
dist[x].Push(tdis[u][t]);
if (y)
{
if (dist[x].Size())
ch[y].Push(dist[x].Top());
if (ch[y].Size() >= 2)
ans.Push(ch[y].Top() + ch[y].Top2());
}
}
col[u] ^= 1;
if (col[u])
++cnt;
else
--cnt;
}
else
{
if (ans.Size())
cout << ans.Top() << '\n';
else if (cnt == 0)
cout << -1 << '\n';
else
cout << 0 << '\n';
}
}
}