zoukankan      html  css  js  c++  java
  • BZOJ4449: [Neerc2015]Distance on Triangulation

    $n leq 50000$的凸多边形,给一个三角剖分,$q leq 100000$组询问每次问两点之间最短路。

    凸多边形是个特殊的图,一般图找单源最短路已经有精美的算法了。然而多组询问呢?

    其实关于路径统计、路径询问的问题,在树上常用的是点分治,每次能统计经过根节点的路径,然后再尽量把他分成较大值较小的两块。在这里可以采用同样的方法。

    一:凸多边形三角剖分的对偶图是一棵树,直接在树上点分。

    二:同样采用“尽量分成较大值较小的两块”的想法,每次选一条“中中”的剖分边,由于经过这条边的剖分边的路径的最短路一定由这条剖分边两个端点到其他点的最短路拼凑而来,因此可以回答所有经过他的询问。

    OK看起来方法二比较好写嘛。。。

    每次分治需要三个信息:剖分边,当前多边形外围的点,以及能回答的询问。

    注意:每次分治完,左右两边的点会比原来多两个(剖分边的),最多进行n次分治,因此空间要开三倍。为了避免因为多点使左边信息覆盖到右边,可以先对右边进行分治再往左边。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 //#include<time.h>
      6 //#include<complex>
      7 #include<algorithm>
      8 #include<stdlib.h>
      9 using namespace std;
     10 
     11 int n,m;
     12 #define maxn 300011
     13 struct Node{int x,y,id;}qq[maxn],line[maxn],h1[maxn],h2[maxn]; int poi[maxn],h3[maxn],h4[maxn];
     14 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
     15 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     16 void insert(int x,int y) {in(x,y); in(y,x);}
     17 
     18 int disx[maxn],disy[maxn];
     19 int que[maxn],head,tail;
     20 int find(int pl,int pr,int x)
     21 {
     22     int L=pl,R=pr;
     23     while (L<R)
     24     {
     25         int mid=(L+R)>>1;
     26         if (poi[mid]>=x) R=mid;
     27         else L=mid+1;
     28     }
     29     return L;
     30 }
     31 void bfs(int s,int pl,int pr,int *dis)
     32 {
     33     head=tail=0;
     34     for (int i=pl;i<=pr;i++) dis[poi[i]]=0x3f3f3f3f;
     35     que[tail++]=s; dis[s]=0;
     36     while (head!=tail)
     37     {
     38         int now=que[head++];
     39         for (int i=first[now];i;i=edge[i].next)
     40         {
     41             Edge &e=edge[i]; if (poi[find(pl,pr,e.to)]!=e.to) continue;
     42             if (dis[e.to]==0x3f3f3f3f) dis[e.to]=dis[now]+1,que[tail++]=e.to;
     43         }
     44     }
     45 }
     46 
     47 int ans[maxn];
     48 void solve(int xl,int xr,int pl,int pr,int ql,int qr)
     49 {
     50     if (xl>xr || pl>pr || ql>qr) return;
     51     int Min=2e9,who=0;
     52     for (int i=xl,tmp=pr-pl+1,tt;i<=xr;i++)
     53     {
     54         int tx=find(pl,pr,line[i].x),ty=find(pl,pr,line[i].y);
     55         if (tx>ty) {tx^=ty; ty^=tx; tx^=ty;}
     56         if ((tt=max(ty-tx,tx+tmp-ty))<Min) Min=tt,who=i;
     57     }
     58     bfs(line[who].x,pl,pr,disx); bfs(line[who].y,pl,pr,disy);
     59     int t1,t2,t3,t4,t5,t6; t1=t2=t3=t4=t5=t6=0;
     60     
     61     for (int i=ql;i<=qr;i++)
     62     {
     63         if ((qq[i].x==line[who].x && qq[i].y==line[who].y) || (qq[i].x==line[who].y && qq[i].y==line[who].x))
     64         {ans[qq[i].id]=1; continue;}
     65         ans[qq[i].id]=min(ans[qq[i].id],min(min(disx[qq[i].x]+disx[qq[i].y],disy[qq[i].x]+disy[qq[i].y]),
     66         min(disx[qq[i].x]+1+disy[qq[i].y],disx[qq[i].y]+1+disy[qq[i].x])));
     67         if (qq[i].x>line[who].x && qq[i].y<line[who].y) h1[++t1]=qq[i];
     68         if ((qq[i].y>line[who].y || qq[i].y<line[who].x) && (qq[i].x>line[who].y || qq[i].x<line[who].x)) h2[++t2]=qq[i];
     69     }
     70     for (int i=1;i<=t1;i++) qq[ql+i-1]=h1[i];
     71     for (int i=1;i<=t2;i++) qq[ql+t1+i-1]=h2[i];
     72     
     73     for (int i=pl;i<=pr;i++)
     74     {
     75         if (poi[i]>=line[who].x && poi[i]<=line[who].y) h3[++t3]=poi[i];
     76         if (poi[i]<=line[who].x || poi[i]>=line[who].y) h4[++t4]=poi[i];
     77     }
     78     for (int i=1;i<=t3;i++) poi[pl+i-1]=h3[i];
     79     for (int i=1;i<=t4;i++) poi[pl+t3+i-1]=h4[i];
     80     
     81     for (int i=xl;i<=xr;i++) if (i!=who)
     82     {
     83         if (line[i].x>=line[who].x && line[i].x<=line[who].y && line[i].y>=line[who].x && line[i].y<=line[who].y)
     84         h1[++t5]=line[i];
     85         else h2[++t6]=line[i];
     86     }
     87     for (int i=1;i<=t5;i++) line[xl+i-1]=h1[i];
     88     for (int i=1;i<=t6;i++) line[xl+t5+i-1]=h2[i];
     89     
     90     solve(xl+t5,xl+t5+t6-1,pl+t3,pl+t3+t4-1,ql+t1,ql+t1+t2-1);
     91     solve(xl,xl+t5-1,pl,pl+t3-1,ql,ql+t1-1);
     92 }
     93 
     94 int main()
     95 {
     96     scanf("%d",&n);
     97     for (int i=1;i<=n-3;i++)
     98     {
     99         scanf("%d%d",&line[i].x,&line[i].y); insert(line[i].x,line[i].y);
    100         if (line[i].x>line[i].y) {line[i].x^=line[i].y; line[i].y^=line[i].x; line[i].x^=line[i].y;}
    101     }
    102     for (int i=1;i<n;i++) insert(i,i+1); insert(1,n);
    103     scanf("%d",&m);
    104     for (int i=1;i<=m;i++)
    105     {
    106         scanf("%d%d",&qq[i].x,&qq[i].y);
    107         if (qq[i].x>qq[i].y) {qq[i].x^=qq[i].y; qq[i].y^=qq[i].x; qq[i].x^=qq[i].y;}
    108         ans[i]=min(qq[i].y-qq[i].x,qq[i].x+n-qq[i].y);
    109         qq[i].id=i;
    110     }
    111     for (int i=1;i<=n;i++) poi[i]=i;
    112     solve(1,n-3,1,n,1,m);
    113     for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    114     return 0;
    115 }
    View Code
  • 相关阅读:
    linux的ip配置
    脚本抓取mongoDB慢查询进程,生成kill语句,快速恢复mongodb CPU打满情况
    python脚本生成sql分库分表语句
    脚本获取rds慢日志
    问题反馈小平台实现 ----python练习
    python脚本 监控MySQL slave 状态
    传统复制的复制结构之间转换
    python判断合法IP并区分内网和外网地址
    ELK单台日志收集系统的搭建
    网站程序文件增量更新脚本
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8547318.html
Copyright © 2011-2022 走看看