UVAlive3662 Another Minimum Spanning Tree 莫队算法

就是莫队的模板题

/*
Memory: 0 KB        Time: 1663 MS
Language: C++11 4.8.2        Result: Accepted
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=100005;
struct Point
{
    int x,y,id;
    bool operator<(const Point &e)const
    {
        if(x==e.x)return y<e.y;
        return x<e.x;
    }
} point[maxn];
struct Edge
{
    int u,v,w;
    bool operator<(const Edge &e)const
    {
        return w<e.w;
    }
} edge[maxn*4];
int tot;
void addedge(int u,int v,int w)
{
    ++tot;
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
}
struct Node
{
    int minval,pos;
    void init()
    {
        minval=INF;
        pos=-1;
    }
} node[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int i,int val,int pos)
{
    while(i>0)
    {
        if(val<node[i].minval)
        {
            node[i].minval=val;
            node[i].pos=pos;
        }
        i-=lowbit(i);
    }
}
int query(int i,int m)
{
    int minval=INF,pos=-1;
    while(i<=m)
    {
        if(node[i].minval<minval)
        {
            minval=node[i].minval;
            pos=node[i].pos;
        }
        i+=lowbit(i);
    }
    return pos;
}
int dis(Point a,Point b)
{
    return abs(a.x-b.x)+abs(a.y-b.y);
}
int c[maxn],b[maxn],n;
void build()
{
    sort(point+1,point+n+1);
    for(int i=1; i<=n; ++i)
        b[i]=c[i]=point[i].y-point[i].x;
    sort(c+1,c+1+n);
    int m=unique(c+1,c+1+n)-(c+1);
    for(int i=1; i<=m; ++i)
        node[i].init();
    for(int i=n; i>0; --i)
    {
        int pos=lower_bound(c+1,c+1+m,b[i])-c;
        int tt=query(pos,m);
        if(tt!=-1)addedge(point[i].id,point[tt].id,dis(point[i],point[tt]));
        update(pos,point[i].x+point[i].y,i);
    }
}
int fa[maxn];
int find(int x)
{
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}
LL solve()
{
    sort(edge+1,edge+1+tot);
    for(int i=1; i<=n; ++i)
        fa[i]=i;
    int cnt=0;
    LL mst=0;
    for(int i=1; i<=tot; ++i)
    {
        int fx=find(edge[i].u);
        int fy=find(edge[i].v);
        if(fx==fy)continue;
        fa[fy]=fx;
        mst+=edge[i].w;
        cnt++;
        if(cnt>=n)break;
    }
    return mst;
}
int main()
{

    int cas=0;
    while(~scanf("%d",&n),n)
    {
        tot=0;
        for(int i=1; i<=n; ++i)
            scanf("%d%d",&point[i].x,&point[i].y),point[i].id=i;
        build();
        for(int i=1; i<=n; ++i)
            point[i].y=-point[i].y;
        build();
        for(int i=1; i<=n; ++i)
            point[i].y=-point[i].y,swap(point[i].x,point[i].y);
        build();
        for(int i=1; i<=n; ++i)
            point[i].y=-point[i].y;
        build();
        printf("Case %d: Total Weight = %lld\n",++cas,solve());
    }
    return 0;
}

时间: 2024-10-10 00:50:07

UVAlive3662 Another Minimum Spanning Tree 莫队算法的相关文章

最小生成树 (Minimum Spanning Tree,MST) ---Kruskal算法

引导问题: 假设要在N个城市之间建立通信联络网,则连通N个城市只需要N - 1条线路.这时,自然会考虑这样一个问题,如何在最省经费的前提下建立这个通信网. 基于问题所建立的定义: 可以用联通网来表示N个城市以及N个城市之间可能设置的连通线路,其中网的顶点表示城市,边表示两城市之间的线路,赋予边的权值表示相应的代价.对于N个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网.现在,要选择这样一颗生成树,也就是使总的耗费最少,这个问题就是构造连通网的的最小代价生成树的问题,即最小生

【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情况下,我们把图看成是一种由"顶点"和"边"组成的抽象网络.在各个"顶点"间可以由"边"连接起来,使两个顶点间相互关联起来.图的结构可以描述多种复杂的数据对象,

BZOJ 2589 Spoj 10707 Count on a tree II 强制在线莫队算法(TLE)

题目大意:给定一棵树,每个节点有一个颜色,多次询问某条路径上颜色数量,强制在线 正解是块状数组,强制在线莫队会TLE到死,想AC这道题的不用看了 如果朴素的跑树上莫队其实并不难- - 但是强制在线 因此我们可以考虑强制在线莫队算法 将树分成O(n^1/3)块,每块大小O(n^2/3) 记录每两块之间的答案.每种颜色的出现次数和哪些点被记录到了答案中 每次查询先找到两端点所在块的端点的答案,然后暴力用莫队转移即可 空间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3) 预处理时间

[Codeforces375D]Tree and Queries(莫队算法)

题意:给定一棵树,每个节点有颜色,对于每个询问(u,k)询问以u为根节点的子树下有多少种颜色出现次数>=k 因为是子树,跟dfs序有关,转化为一段区间,可以用莫队算法求解 直接用一个数组统计出现次数>=k的颜色 Code #include <cstdio> #include <algorithm> #include <cmath> #define N 100010 using namespace std; int n,m,A[N],bl[N],Ans[N],

莫队算法小结(Markdown版)

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉 好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m个询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为0则输出01 仔细观察发现,令x表示x这个值出现的次

POJ 3241 Object Clustering 莫队算法

第n-k大曼哈顿距离,莫队算法裸题 Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 1584   Accepted: 366 Description We have N (N ≤ 10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simp

Geeks : Kruskal’s Minimum Spanning Tree Algorithm 最小生成树

寻找图中最小连通的路径,图如下: 算法步骤: 1. Sort all the edges in non-decreasing order of their weight. 2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. If cycle is not formed, include this edge. Else, discard it. 3. Repeat st

莫队算法小结

唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为则输出0/1 仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区

【算法】莫队算法初探

[算法介绍] 莫队算法是用于离线处理处理区间问题的一类算法,非常易于理解和上手,应用面十分广泛,甚至还可以在树上进行操作. 当我们得到$[L,R]$的答案之后,如果能够以较低的复杂度扩展得到$[L-1,R],[L+1,R],[L,R-1],[L,R+1]$的答案,我们就可以使用莫队算法,通常这个扩展的复杂度是$O(1)$或$O(logn)$. 如果我们对于每个询问都暴力移动左右端点,那么复杂度肯定是$O(n^2)$的,而莫队算法的精髓就在于结合了分块的思想. 设扩展一次的复杂度为$O(f(n))