• bzoj4449 [Neerc2015]Distance on Triangulation


    4449: [Neerc2015]Distance on Triangulation

    Time Limit: 100 Sec  Memory Limit: 512 MB
    Submit: 205  Solved: 69
    [Submit][Status][Discuss]

    Description

    给定一个凸n边形,以及它的三角剖分。再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b。

    Input

     第一行一个整数n(n <= 50000),代表有n个点。点1,2,3,…,n是凸多边形上是顺时针排布的。

    接下来n-3行,每行两个整数(x,y),代表(x,y)之间有一条剖分边。
    接下来是一个整数q(q <= 100000),代表有q组询问。
    接下来q行是两个整数(a,b)。

    Output

    输出q行,每行一个整数代表最少边数。

    Sample Input

    6
    1 5
    2 4
    5 2
    5
    1 3
    2 5
    3 4
    6 3
    6 6

    Sample Output

    2
    1
    1
    3
    0
    分析:这题太神了......
       做法上和bzoj4456是一样的,但是代码很难写.
       分界线上的两个点是要同时出现在左区间和右区间的.分治后左区间+右区间的长度就不等于原区间的长度了. 怎么办呢? 往右扩展呗.,重叠的这部分的元素实际上属于左区间,右区间占着这些位置罢了. 这样就有一个问题:如果先处理左区间,再处理右区间,本该属于左区间的重叠部分就会被右区间给占了,这是不合法的,所以只有先处理右区间才行.  数组要开2倍才行.
       血的教训:dfs时不要开全局变量(如果不是统计最优解/答案的话).
       优化:bfs代替dijkstra. 每次只松弛在当前区间内的点.
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 2000010,inf = 0x7fffffff;
    int n,head[maxn],to[maxn],nextt[maxn],tot = 1,a[maxn],Q,ans[maxn],d[maxn][2],Tim,vis[maxn];
    int cnt1,cnt2,cnt3,cnt4,cnt5,cnt6,tmp3[maxn],tmp4[maxn],num;
    
    struct node
    {
        int x,y,id;
    } e[maxn],q[maxn],tmp1[maxn],tmp2[maxn],tmp5[maxn],tmp6[maxn];
    
    void add(int x,int y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    int find(int l,int r,int pos)
    {
        int anss = 0;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (a[mid] == pos)
            {
                anss = mid;
                break;
            }
            if (a[mid] < pos)
                l = mid + 1;
            else
                r = mid - 1;
        }
        return anss;
    }
    
    int getans(int x,int y)
    {
        int temp = inf;
        temp = min(d[x][0] + d[y][0],temp);
        temp = min(d[x][1] + d[y][1],temp);
        temp = min(d[x][0] + d[y][1] + 1,temp);
        temp = min(d[x][1] + d[y][0] + 1,temp);
        return temp;
    }
    
    
    void bfs(int S,int l,int r,int opt)
    {
        Tim++;
        vis[S] = Tim;
        queue <int> q;
        q.push(S);
        d[S][opt] = 0;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = head[u]; i; i = nextt[i])
            {
                int v = to[i];
                if (a[find(l,r,v)] == v && vis[v] != Tim)
                {
                    vis[v] = Tim;
                    q.push(v);
                    d[v][opt] = d[u][opt] + 1;
                }
            }
        }
    }
    
    
    void solve(int l1,int r1,int l2,int r2,int l3,int r3) //对角线,点,询问
    {
        if (l3 > r3)
            return;
        int cnt1 = 0,cnt2 = 0,cnt3 = 0,cnt4 = 0,cnt5 = 0,cnt6 = 0;
        node res = e[l1];
        int maxx = inf,cur;
        for (int i = l1; i <= r1; i++)
        {
            int x = find(l2,r2,e[i].x),y = find(l2,r2,e[i].y);
            if (x > y)
                swap(x,y);
            int temp = max(y - x,r2 - l2 + 1 - (y - x));
            if (temp < maxx)
            {
                maxx = temp;
                res = e[i];
                cur = i;
            }
        }
        int X = res.x,Y = res.y;
        bfs(X,l2,r2,0);
        bfs(Y,l2,r2,1);
        for (int i = l3; i <= r3; i++)
        {
            if (q[i].x == X && q[i].y == Y)
            {
                ans[q[i].id] = 1;
                continue;
            }
            ans[q[i].id] = min(ans[q[i].id],getans(q[i].x,q[i].y));
            if (q[i].x > X && q[i].x < Y && q[i].y > X && q[i].y < Y)
                tmp5[++cnt5] = q[i];
            else if ((q[i].x < X || q[i].x > Y) && (q[i].y < X || q[i].y > Y))
                tmp6[++cnt6] = q[i];
        }
        for (int i = l1; i <= r1; i++)
        {
            if (cur == i)
                continue;
            if (e[i].x >= X && e[i].y <= Y)
                tmp1[++cnt1] = e[i];
            else
                tmp2[++cnt2] = e[i];
        }
        for (int i = l2; i <= r2; i++)
        {
            if (a[i] >= X && a[i] <= Y)
                tmp3[++cnt3] = a[i];
            if (a[i] <= X || a[i] >= Y)
                tmp4[++cnt4] = a[i];
        }
        for (int i = 1; i <= cnt1; i++)
            e[l1 + i - 1] = tmp1[i];
        for (int i = 1; i <= cnt2; i++)
            e[l1 + cnt1 + i - 1] = tmp2[i];
        for (int i = 1; i <= cnt3; i++)
            a[l2 + i - 1] = tmp3[i];
        for (int i = 1; i <= cnt4; i++)
            a[l2 + cnt3 + i - 1] = tmp4[i];
        for (int i = 1; i <= cnt5; i++)
            q[l3 + i - 1] = tmp5[i];
        for (int i = 1; i <= cnt6; i++)
            q[l3 + cnt5 + i - 1] = tmp6[i];
        solve(l1 + cnt1,l1 + cnt1 + cnt2 - 1,l2 + cnt3,l2 + cnt3 + cnt4 - 1,l3 + cnt5,l3 + cnt5 + cnt6 - 1);
        solve(l1,l1 + cnt1 - 1,l2,l2 + cnt3 - 1,l3,l3 + cnt5 - 1);
    }
    
    int main()
    {
        memset(ans,127 / 3,sizeof(ans));
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
            a[i] = i;
        for (int i = 1; i <= n - 3; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (x > y)
                swap(x,y);
            add(x,y);
            add(y,x);
            e[i].x = x;
            e[i].y = y;
        }
        for (int i = 1; i <= n; i++)
        {
            add(i,i % n + 1);
            add(i % n + 1,i);
        }
        scanf("%d",&Q);
        for (int i = 1; i <= Q; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (x > y)
                swap(x,y);
            if (x == y)
                ans[i] = 0;
            else if (x % n + 1 == y || y % n + 1 == x)
                ans[i] = 1;
            else
            {
                q[++num].x = x;
                q[num].y = y;
                q[num].id = i;
                ans[i] = min(ans[i],min(y - x,n + x - y));
            }
        }
        solve(1,n - 3,1,n,1,num);
        for (int i = 1; i <= Q; i++)
            printf("%d
    ",ans[i]);
    
        return 0;
    }
  • 相关阅读:
    《Mysql
    《Redis
    《pt-query-digest 剖析 Mysql 慢日志》
    《Redis
    《Redis
    《Redis
    《Redis
    《Redis
    python中__new__()与__init__()的区别
    Python常见综合面试题
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8711376.html
Copyright © 2020-2023  润新知