This is a very simple problem. You are given N points. Some points may be repeated. The weight (distance) between two points is given by the Manhattan distance between the two points. Find the weight of a Minimum Spanning Tree that spans these N points.
The input consists of:
One line with one integer N (1≤N≤100000), the number of points,
N lines each with two integers x and y (0≤x,y<1000), the coordinates of each point.
Output one line with a single integer: The weight of a Minimum Spanning Tree that spans these N points.
Sample Input 1 | Sample Output 1 |
---|---|
4 0 0 0 1 1 0 1 1 |
3 |
Sample Input 2 | Sample Output 2 |
---|---|
5 0 0 10 0 10 0 11 1 12 2 |
14 |
#include
using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
LL inf = 1e18;
int n;
int tot;
int father[maxn];
struct point
{
int x, y, id;
bool operator <(const point &res) const
{
if(x == res.x) return y < res.y;
else return x < res.x;
}
} Point[maxn<<4];
struct edge
{
int u, v;
LL w;
bool operator <(const edge &res) const
{
return w < res.w;
}
} Edge[maxn<<10];
struct node
{
int l, r, id;
LL Min;
} Node[maxn<<6];
void add(int u, int v, LL w)
{
Edge[++tot].u = u;
Edge[tot].v = v;
Edge[tot].w = w;
}
void Pushup(int i)
{
int lson = i<<1;
int rson = lson|1;
if(Node[lson].Min <= Node[rson].Min)
{
Node[i].Min = Node[lson].Min;
Node[i].id = Node[lson].id;
}
else
{
Node[i].Min = Node[rson].Min;
Node[i].id = Node[rson].id;
}
}
void build(int i, int l, int r)
{
Node[i].l = l;
Node[i].r = r;
Node[i].Min = inf;
Node[i].id = -1;
if(l == r) return;
int f = i;
int mid = (l + r)>>1;
i <<= 1;
build(i, l, mid);
build(i|1, mid + 1, r);
//Pushup(f);
}
void update(int i, int loc, LL value, int id)
{
if(Node[i].l == Node[i].r)
{
if(value >= Node[i].Min) return;
Node[i].Min = value;
Node[i].id = id;
return;
}
int f = i;
i <<= 1;
if(loc <= Node[i].r) update(i, loc, value, id);
else update(i|1, loc, value, id);
Pushup(f);
}
pair query(int i, int l, int r)
{
if(Node[i].l == l && Node[i].r == r)
{
return make_pair(Node[i].Min, Node[i].id);
}
i <<= 1;
if(r <= Node[i].r) return query(i, l, r);
else if(l >= Node[i|1].l) return query(i|1, l, r);
else
{
pair pp1 = query(i, l, Node[i].r);
pair pp2 = query(i|1, Node[i|1].l, r);
if(pp1.first <= pp2.first) return pp1;
else return pp2;
}
}
void Tran(int type)
{
if(type == 1)
{
sort(Point + 1, Point + n + 1);
return;
}
else if(type == 2 || type == 4)
{
for(int i = 1; i <= n; i++)
{
swap(Point[i].x, Point[i].y);
}
sort(Point + 1, Point + n + 1);
return;
}
else if(type == 3)
{
for(int i = 1; i <= n; i++)
{
Point[i].x = -Point[i].x;
}
sort(Point + 1, Point + n + 1);
return;
}
}
void getGraph()
{
for(int i = 1; i <= 4; i++)
{
Tran(i);
build(1, 0, 4000);
for(int j = n; j >= 1; j--)
{
int loc = Point[j].y - Point[j].x;
loc += 2000;
pair pp = query(1, loc, 4000);
if(pp.first < inf)
{
int id = pp.second;
add(Point[j].id, id, pp.first - LL(Point[j].x + Point[j].y));
}
update(1, loc, (LL)(Point[j].x + Point[j].y), Point[j].id);
}
}
}
void init()
{
tot = 0;
for(int i = 1; i <= n; i++) father[i] = i;
}
int Find(int x)
{
if(father[x] == x) return x;
else return father[x] = Find(father[x]);
}
LL kruscal()
{
LL ans = 0;
int judge = 0;
sort(Edge + 1, Edge + tot + 1);
for(int i = 1; i <= tot; i++)
{
int u = Edge[i].v;
int v = Edge[i].u;
LL w = Edge[i].w;
int f1 = Find(u);
int f2 = Find(v);
if(f1 != f2)
{
judge++;
ans += w;
father[f1] = f2;
}
if(judge == n - 1) break;
}
return ans;
}
int main()
{
freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &Point[i].x, &Point[i].y);
Point[i].id = i;
}
init();
getGraph();
printf("%lld\n", kruscal());
return 0;
}
树状数组:
#include
using namespace std;
typedef long long LL;
inline bool scan_d(int &num)
{
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
const int maxn = 100000 + 10;
LL inf = 1e18;
int n;
int tot;
int father[maxn];
struct point
{
int x, y, id;
bool operator <(const point &res) const
{
if(x == res.x) return y < res.y;
else return x < res.x;
}
} Point[maxn<<4];
struct edge
{
int u, v;
LL w;
bool operator <(const edge &res) const
{
return w < res.w;
}
} Edge[maxn<<10];
struct BITnode{
LL w;
int id;
}Tree[maxn<<1];
LL H[maxn<<1];
int num;
int lowbit(int x)
{
return x&(-x);
}
int Hash(LL key)
{
return lower_bound(H, H + num, key) - H + 1;
}
void add_edge(int u, int v, LL w)
{
Edge[++tot].u = u;
Edge[tot].v = v;
Edge[tot].w = w;
}
void Tran(int type)
{
if(type == 1)
{
sort(Point + 1, Point + n + 1);
return;
}
else if(type == 2 || type == 4)
{
for(int i = 1; i <= n; i++)
{
swap(Point[i].x, Point[i].y);
}
sort(Point + 1, Point + n + 1);
return;
}
else if(type == 3)
{
for(int i = 1; i <= n; i++)
{
Point[i].x = -Point[i].x;
}
sort(Point + 1, Point + n + 1);
return;
}
}
void add(int loc, LL v, int id)
{
for(int i = loc; i >= 1; i -= lowbit(i))
{
if(Tree[i].w > v)
{
Tree[i].w = v;
Tree[i].id = id;
}
}
}
int query(int loc)
{
LL Min = inf;
int id = -1;
for(int i = loc; i <= num; i += lowbit(i))
{
if(Tree[i].w < Min)
{
Min = Tree[i].w;
id = i;
}
}
return id;
}
void getGraph()
{
for(int i = 1; i <= 4; i++)
{
Tran(i);
num = 0;
for(int j = n; j >= 1; j--)
{
Tree[j].id = -1;
Tree[j].w = inf;
LL key = LL(Point[j].y - Point[j].x);
H[num++] = key;
}
sort(H, H + num);
num = unique(H, H + num) - H;
for(int j = n; j >= 1; j--)
{
LL key = LL(Point[j].y - Point[j].x);
LL v = LL(Point[j].x + Point[j].y);
int loc = Hash(key);
int id = query(loc);
if(id != -1)
{
add_edge(Point[j].id, Tree[id].id, Tree[id].w - v);
}
add(loc, v, Point[j].id);
}
}
}
void init()
{
tot = 0;
for(int i = 1; i <= n; i++) father[i] = i;
}
int Find(int x)
{
if(father[x] == x) return x;
else return father[x] = Find(father[x]);
}
LL kruscal()
{
LL ans = 0;
int judge = 0;
sort(Edge + 1, Edge + tot + 1);
for(int i = 1; i <= tot; i++)
{
int u = Edge[i].v;
int v = Edge[i].u;
LL w = Edge[i].w;
int f1 = Find(u);
int f2 = Find(v);
if(f1 != f2)
{
judge++;
ans += w;
father[f1] = f2;
}
if(judge == n - 1) break;
}
return ans;
}
int main()
{
// freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
//scanf("%d%d", &Point[i].x, &Point[i].y);
scan_d(Point[i].x);
scan_d(Point[i].y);
Point[i].id = i;
}
init();
getGraph();
printf("%lld\n", kruscal());
return 0;
}