【HDU】5817 Ice Walls【极角排序+树状数组+最短路】

来源:互联网 发布:男士护肤国产品牌 知乎 编辑:程序博客网 时间:2024/05/17 06:45

题目链接:Ice Walls

题目大意:给出平面上一些与坐标轴平行且严格不相交的线段,穿过线段额外花费k时间,平面上移动一单位欧式距离花费1,求st的最短路。
题目分析:横竖线段分别考虑,先考虑竖线。枚举顶点,求出点和线段到顶点的x轴距离,排序,然后双指针,线段覆盖的是一个极角区间,因此可以树状数组求贡献。横线同理。

#include <bits/stdc++.h>using namespace std ;typedef long long LL ;typedef pair < double , int > pii ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 1005 ;const double eps = 1e-8 ;const double pi = acos ( -1.0 ) ;struct Point {    int x , y ;    Point () {}    Point ( int x , int y ) : x ( x ) , y ( y ) {}    Point operator - ( const Point& a ) const {        return Point ( x - a.x , y - a.y ) ;    }    Point operator + ( const Point& a ) const {        return Point ( x + a.x , y + a.y ) ;    }    void input () {        scanf ( "%d%d" , &x , &y ) ;    }    double angle () {        return atan2 ( y , x ) ;    }    double dis () {        return sqrt ( 1.0 * x * x + 1.0 * y * y ) ;    }} ;struct Line {    int u , v ;} ;struct Node {    int dis , idx ;    bool operator < ( const Node& a ) const {        return dis < a.dis ;    }} ;Point p[MAXN] ;Line seg[MAXN] ;vector < pii > G ;Node a[MAXN << 1] ;int n , m , K , s , t ;int c[MAXN] ;double dis[MAXN][MAXN] ;double d[MAXN] ;int vis[MAXN] ;int rnk[MAXN] ;void add ( int x , int n , int v ) {    for ( int i = x ; i ; i -= i & -i ) {        c[i] += v ;    }}int sum ( int x , int n ) {    int ans = 0 ;    for ( int i = x ; i <= n ; i += i & -i ) {        ans += c[i] ;    }    return ans ;}int lfind ( double x , int l = 0 , int r = G.size () - 1 ) {    while ( l < r ) {        int m = l + r >> 1 ;        if ( x + eps < G[m].first ) r = m ;        else l = m + 1 ;    }    if ( x + eps > G[l].first ) ++ l ;    return l + 1 ;}int rfind ( double x , int l = 0 , int r = G.size () - 1 ) {    while ( l < r ) {        int m = l + r + 1 >> 1 ;        if ( G[m].first + eps < x ) l = m ;        else r = m - 1 ;    }    if ( G[l].first + eps > x ) -- l ;    return l + 1 ;}void deal ( int o , int cnt ) {    int num = G.size () ;    sort ( G.begin () , G.end () ) ;    sort ( a , a + cnt ) ;    for ( int i = 1 ; i <= num ; ++ i ) {        rnk[G[i - 1].second] = i ;        c[i] = 0 ;    }    for ( int i = 0 ; i < cnt ; ++ i ) {        int idx = a[i].idx ;        if ( idx < 0 ) {            int u = seg[-idx].u ;            int v = seg[-idx].v ;            double angl = ( p[u] - p[o] ).angle () ;            double angr = ( p[v] - p[o] ).angle () ;            if ( angl > angr ) swap ( angl , angr ) ;            int l = lfind ( angl ) ;            int r = rfind ( angr ) ;            add ( r , num , 1 ) ;            add ( l - 1 , num , -1 ) ;        } else {            LL t = 1LL * K * sum ( rnk[idx] , num ) ;            dis[o][idx] += t ;            dis[idx][o] += t ;        }    }}void dij ( int s ) {    for ( int i = 1 ; i <= m ; ++ i ) {        d[i] = dis[s][i] ;        vis[i] = 0 ;    }    d[s] = 0 ;    vis[s] = 1 ;    for ( int i = 1 ; i < m ; ++ i ) {        double minv = 1e60 ;        int u = s ;        for ( int j = 1 ; j <= m ; ++ j ) {            if ( !vis[j] && d[j] < minv ) {                u = j ;                minv = d[j] ;            }        }        vis[u] = 1 ;        for ( int j = 1 ; j <= m ; ++ j ) {            if ( !vis[j] && d[u] + dis[u][j] < d[j] ) {                d[j] = d[u] + dis[u][j] ;            }        }    }}void solve () {    m = 0 ;    scanf ( "%d%d" , &n , &K ) ;    for ( int i = 1 ; i <= n ; ++ i ) {        p[++ m].input () ;        seg[i].u = m ;        p[++ m].input () ;        seg[i].v = m ;    }    p[++ m].input () ;    s = m ;    p[++ m].input () ;    t = m ;    for ( int i = 1 ; i <= m ; ++ i ) {        for ( int j = i + 1 ; j <= m ; ++ j ) {            dis[i][j] = dis[j][i] = ( p[i] - p[j] ).dis () ;        }    }    for ( int i = 1 ; i <= m ; ++ i ) {        int cnt = 0 ;        G.clear () ;        for ( int j = 1 ; j <= m ; ++ j ) if ( j != i ) {            if ( p[j].x > p[i].x ) {                G.push_back ( pii ( ( p[j] - p[i] ).angle () , j ) ) ;                a[cnt].dis = p[j].x - p[i].x ;                a[cnt ++].idx = j ;            }        }        for ( int j = 1 ; j <= n ; ++ j ) {            int x = p[seg[j].u].x ;            if ( x == p[seg[j].v].x && x > p[i].x ) {                a[cnt].dis = x - p[i].x ;                a[cnt ++].idx = -j ;            }        }        deal ( i , cnt ) ;        cnt = 0 ;        G.clear () ;        for ( int j = 1 ; j <= m ; ++ j ) if ( j != i ) {            if ( p[j].y > p[i].y ) {                G.push_back ( pii ( ( p[j] - p[i] ).angle () , j ) ) ;                a[cnt].dis = p[j].y - p[i].y ;                a[cnt ++].idx = j ;            }        }        for ( int j = 1 ; j <= n ; ++ j ) {            int y = p[seg[j].u].y ;            if ( y == p[seg[j].v].y && y > p[i].y ) {                a[cnt].dis = y - p[i].y ;                a[cnt ++].idx = -j ;            }        }        deal ( i , cnt ) ;    }    dij ( s ) ;    printf ( "%.10f\n" , d[t] ) ;}int main () {    int T ;    scanf ( "%d" , &T ) ;    for ( int i = 1 ; i <= T ; ++ i ) {        solve () ;    }    return 0 ;}

压缩后代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef pair<double,int>pii;#define clr(a,x) memset(a,x,sizeof a)const int MAXN=1005;const double eps=1e-8;const double pi=acos(-1.0);struct Point{    int x,y;    Point(){}    Point(int x,int y):x(x),y(y){}    Point operator - (const Point &a)const{return Point (x-a.x,y-a.y);}    Point operator + (const Point &a)const{return Point (x+a.x,y+a.y);}    void input(){scanf("%d%d",&x,&y);}    double angle(){return atan2(y,x);}    double dis(){return sqrt(1.0*x*x+1.0*y*y);}}p[MAXN];struct Line{    int u,v;}seg[MAXN];struct Node{    int dis,idx;    Node(){}    Node(int d,int i):dis(d),idx(i){}    bool operator < (const Node&a)const{return dis<a.dis;}}a[MAXN<<1];pii G[MAXN];int n,m,K,s,t,c[MAXN],vis[MAXN],rnk[MAXN],num;double dis[MAXN][MAXN],d[MAXN];void add(int x,int n,int v){    for(int i=x;i;i-=i&-i)c[i]+=v;}int sum(int x,int n,int ans=0){    for(int i=x;i<=n;i+=i&-i)ans+=c[i];    return ans;}int lfind(double x,int l=0,int r=num-1){    for(int m=l+r>>1;l<r;m=l+r>>1)x+eps<G[m].first?r=m:l=m+1;    if(x+eps>G[l].first)++l;    return l+1;}int rfind(double x,int l=0,int r=num-1){    for(int m=l+r+1>>1;l<r;m=l+r+1>>1)G[m].first+eps<x?l=m:r=m-1;    if(G[l].first+eps>x)--l;    return l+1;}void deal(int o,int cnt){    int i,idx;    sort(G,G+num);    sort(a,a+cnt);    for(i=1;i<=num;++i)rnk[G[i-1].second]=i,c[i]=0;    for(i=0,idx=a[i].idx;i<cnt;++i,idx=a[i].idx){        if(idx<0){            int u=seg[-idx].u,v=seg[-idx].v;            double angl=(p[u]-p[o]).angle();            double angr=(p[v]-p[o]).angle();            if(angl>angr)swap(angl,angr);            int l=lfind(angl),r=rfind(angr);            add(r,num,1);            add(l-1,num,-1);        }else{            LL t=1LL*K*sum(rnk[idx],num);            dis[o][idx]+=t;            dis[idx][o]+=t;        }    }}void dij(int s){    int i,j,u;    for(i=1;i<=m;++i)d[i]=dis[s][i],vis[i]=0;    for(d[s]=0,vis[s]=1,i=1,j,u;i<m;++i){        double minv=1e60;        for(u=s,j=1;j<=m;++j)if(!vis[j]&&d[j]<minv)minv=d[u=j];        for(vis[u]=1,j=1;j<=m;++j)if(!vis[j]&&d[u]+dis[u][j]<d[j])d[j]=d[u]+dis[u][j];    }}void solve(){    m=0;    scanf("%d%d",&n,&K);    for(int i=1;i<=n;++i)p[seg[i].u=++m].input(),p[seg[i].v=++m].input();    p[s=++m].input(),p[t=++m].input();    for(int i=1;i<=m;++i)for(int j=i+1;j<=m;++j)dis[i][j]=dis[j][i]=(p[i]-p[j]).dis();    for(int i=1,j,cnt;i<=m;++i){        for(num=0,cnt=0,j=1;j<=m;++j)if(j!=i&&p[j].x>p[i].x){            G[num++]=pii((p[j]-p[i]).angle(),j);            a[cnt++]=Node(p[j].x-p[i].x,j);        }        for(j=1;j<=n;++j){            int x=p[seg[j].u].x;            if(x==p[seg[j].v].x&&x>p[i].x)a[cnt++]=Node(x-p[i].x,-j);        }        deal(i,cnt);        for(num=0,cnt=0,j=1;j<=m;++j)if(j!=i&&p[j].y>p[i].y){            G[num++]=pii((p[j]-p[i]).angle(),j);            a[cnt++]=Node(p[j].y-p[i].y,j);        }        for(j=1;j<=n;++j){            int y=p[seg[j].u].y;            if(y==p[seg[j].v].y&&y>p[i].y)a[cnt++]=Node(y-p[i].y,-j);        }        deal(i,cnt);    }    dij(s);    printf("%.10f\n",d[t]);}int main(){    int T;    scanf("%d",&T);    for(int i=1;i<=T;++i)solve();    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 一师一优课有账号忘记密码怎么办? 长沙转户口档案怎么办 二战迁户口档案怎么办 本人户口页丢失怎么办 户口迁出原籍档案怎么办 户口本丢了一页怎么办 户口本少了一页怎么办 户口页丢了怎么办 公司要社保卡怎么办 公务员面试缺考怎么办 word文档未标签怎么办 暂住证到期了怎么办t 考驾照没暂住证怎么办 南京暂住证过期了怎么办 南京桥北暂住证怎么办 冠状沟红痒一年多了怎么办 介仓身上痒怎么办 专升本考试怎么办 专升本毕业论文怎么办 手机扫码模糊怎么办 iphone相册闪退怎么办 快件签收扫描失败怎么办 创业迷茫的时候怎么办 月经期间腰酸痛怎么办 被重庆微跑骗了怎么办 遴选到中央房子怎么办 转了户口社保怎么办 政府咨询电话打不通怎么办 公务员准考证丢了怎么办 行测老打40多分怎么办 网上没有报名的怎么办? 上大学转户口怎么办 梅菜扣肉勾芡怎么办 有个精神病妈妈怎么办 妈得了精神病该怎么办 思维不正常的人怎么办 妈妈是个精神病怎么办 我老婆有精神病怎么办 在郑州怎么办完税证明 中专没考上大专怎么办 考研两次没考上怎么办