NOIP2013提高组Day 1

版权声明:吸吸 https://blog.csdn.net/walk_dog/article/details/81190216

T2

这道题其实就是就是求逆序对数目,然后我们可以想到第一个数组里第k大的数对应第二个数组里第k大的数
求逆序对个数第一个想到的就是归并排序了

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;
const int MAXN = 1e5+5, MOD = 99999997;
int n, answer;
struct name {
    int num, Idx;
}a[MAXN], b[MAXN];
int Tmp[MAXN], Tmp2[MAXN];

bool comp(name x, name y){ return x.num < y.num; }

void Merge(int left, int right)
{
    if(left >= right) return ;
    int mid = left + (right - left) / 2;
    Merge(left, mid);
    Merge(mid+1, right);
    int i = left, j = mid+1, k = left;
    while(i<=mid && j<=right)
    {
        if(Tmp[i] > Tmp[j])
        {
            Tmp2[k++] = Tmp[j++];
            answer += mid-i+1;
            answer %= MOD;
        }
        else Tmp2[k++] = Tmp[i++];
    }
    while(i<=mid) Tmp2[k++] = Tmp[i++];
    while(j <= right) Tmp2[k++] = Tmp[j++];
    for(int l = left; l<= right; l++)
    {
        Tmp[l] = Tmp2[l];
    }
}

int main()
{
//  freopen("match.in","r",stdin);
//  freopen("match.out","w",stdout);
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i].num);
        a[i].Idx = i;
    }
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &b[i].num);
        b[i].Idx = i;
    }
    sort(a+1, a+n+1, comp);
    sort(b+1, b+n+1, comp);
    for(int i = 1; i <= n; i++)
    {
        Tmp[a[i].Idx] = b[i].Idx;
    }
    Merge(1, n);
    printf("%d", answer);
    return 0;
}

T3

可以想到用最大生成树,求到了最大生成树之后,我们便考虑如何求出两个节点之间最小边权的最大值,因为这两点之间的路径是唯一的,于是我们可以通过LCA求出答案。

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;

typedef long long ll;
const int MAXN = 1e6+5;
int w[MAXN][21],p[MAXN][21],head[MAXN],deep[MAXN],fa[MAXN];
struct nodea{ int x,y,c; } t[MAXN];
struct nodeb{ int x,y,c,g; } h[MAXN];
int INF = 999999999, len, n, m, q;

void px(int l, int r)
{
    int x=l,y=r, mid=t[(l+r)/2].c;
    while(x <= y)
    {
        while(t[x].c > mid) x++;
        while(t[y].c<mid) y--;
        if(x <= y)
        {
            nodea pt = t[x];
            t[x] = t[y];
            t[y] = pt;
            x++;
            y--;
        }
    }
    if(l < y) px(l,y);
    if(x<r) px(x,r);
}

int min(int x,int y){ return x<y?x:y; }

int init()
{
    for(int i = 1; i <= n; i++)
    {
        fa[i] = i;
        head[i] = 0;
        deep[i] = 0;
    }
}

void ins(int x, int y, int c)
{
    len++;
    h[len].x = x;
    h[len].y = y;
    h[len].c = c;
    h[len].g = head[x];
    head[x] = len;
}

int find(int t)
{
    if(fa[t] == t) return t;
    else return fa[t]=find(fa[t]);
}
void kruskal()
{
    int p = 0;
    for(int i = 1; i <= m; i++)
    {
        int tx = find(t[i].x);
        int ty = find(t[i].y);
        if(tx != ty)
        {
            fa[tx] = ty;
            ins(t[i].x,t[i].y,t[i].c);
            ins(t[i].y,t[i].x,t[i].c);
            p++;
            if(p == n-1) break;
        }
    }
}

void dfs(int u)
{
    for(int i = head[u]; i > 0; i=h[i].g)
    {
        int y = h[i].y;
        if(deep[y]==0)
        {
            deep[y]=deep[u]+1;
            p[y][0]=u;
            w[y][0]=h[i].c;
            dfs(y);
        }
    }
}

void ycl()
{
    for(int i = 1; i <= n; i++)
    {
        if(deep[i] == 0)
        {
            deep[i] = 1;
            p[i][0] = 0;
            dfs(i);
        }    
    }
    dfs(1);
    for(int i = 1; i <= 20; i++)
    {
        for(int x = 1; x <= n; x++)
        {
            p[x][i] = p[p[x][i-1]][i-1];
            w[x][i]=min(w[x][i-1], w[p[x][i-1]][i-1]);
        }
    }
}

int lca(int x,int y)
{
    int ans=INF;
    if(deep[x] < deep[y])
    {
        int t = x;
        x = y;
        y = t;
    }
    for(int i = 20; i >= 0; i--)
        if(deep[p[x][i]] >= deep[y])
        {
            ans = min(ans,w[x][i]);
            x = p[x][i];
        }
    if(x == y) return ans;
    for(int i = 20; i >= 0; i--)
        if(p[x][i] != p[y][i])
        {
            ans = min(ans, min(w[x][i], w[y][i]));
            x = p[x][i];
            y = p[y][i];
        }
    ans = min(ans, min(w[x][0], w[y][0]));
    return ans;
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++)
        scanf("%d%d%d", &t[i].x, &t[i].y, &t[i].c);
    px(1, m);
    init();
    kruskal();
    ycl();
    scanf("%d", &q);
    for(int i = 1; i <= q; i++)
    {
        int dx = 0, dy = 0;
        scanf("%d%d", &dx, &dy);
        if(find(dx) != find(dy)) printf("-1\n");
        else printf("%d\n",lca(dx,dy));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/walk_dog/article/details/81190216