zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程
    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介
    001 01 Android 零基础入门 01 Java基础语法 01 Java初识 01 导学
    001 Android Studio 首次编译执行项目过程中遇到的几个常见问题
    Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器
    Dora.Interception,为.NET Core度身打造的AOP框架 [1]:更加简练的编程体验
    监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
    轻量级ORM框架——第二篇:Dapper中的一些复杂操作和inner join应该注意的坑
    轻量级ORM框架——第一篇:Dapper快速学习
    CF888G Xor-MST(异或生成树模板)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8711376.html
Copyright © 2011-2022 走看看