zoukankan      html  css  js  c++  java
  • BZOJ3536 : [Usaco2014 Open]Cow Optics

    枚举最后光线射到终点的方向,求出从起点出发以及从终点出发的光路,扫描线+树状数组统计交点个数即可。

    注意当光路成环时,对应的两个方向应该只算一次。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100010;
    const ll inf=1LL<<50;
    inline void read(int&a){
      char c;bool f=0;a=0;
      while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
      if(c!='-')a=c-'0';else f=1;
      while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
      if(f)a=-a;
    }
    int n,i,j,k,q[N],g[N][4],dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};char d[N],w[N*2];
    int cb,cc,ce,cf,bit[N*6];ll f[N*6],ans;
    struct P{
      ll x,y;
      P(){}
      P(ll _x,ll _y){x=_x,y=_y;}
      void read(){
        int a,b;
        ::read(a),::read(b);
        x=a,y=b;
      }
    }B,a[N],b[N*2],c[N*2];
    struct E{
      ll x,l,r;int t;
      E(){}
      E(ll _x,ll _l,ll _r,int _t){x=_x,l=_l,r=_r,t=_t;}
    }e[N*6];
    inline bool cmpx(int x,int y){return a[x].x==a[y].x?a[x].y<a[y].y:a[x].x<a[y].x;}
    inline bool cmpy(int x,int y){return a[x].y==a[y].y?a[x].x<a[y].x:a[x].y<a[y].y;}
    inline bool cmpe(const E&a,const E&b){return a.x==b.x?a.t>b.t:a.x<b.x;}
    int work(P o,int k,P*q,int&m){
      q[m=1]=o;
      int i,j=-1;ll dis;
      for(i=0;i<=n;i++){
        if(k==0&&!(a[i].x==o.x&&a[i].y<=o.y))continue;
        if(k==1&&!(a[i].x==o.x&&a[i].y>=o.y))continue;
        if(k==2&&!(a[i].y==o.y&&a[i].x<=o.x))continue;
        if(k==3&&!(a[i].y==o.y&&a[i].x>=o.x))continue;
        ll t=1LL*abs(a[i].x-o.x)+1LL*abs(a[i].y-o.y);
        if(!t)continue;
        if(j<0||t<dis)j=i,dis=t;
      }
      while(~j){
        q[++m]=a[j];
        w[m]=k;
        if(!j)return 2;
        if(m>2&&q[m].x==q[2].x&&q[m].y==q[2].y&&w[m]==w[2])return 1;
        if(d[j]=='/')k=(k+2)&3;else k=3-k;
        o=a[j];
        j=g[j][k];
      }
      q[++m]=o;
      q[m].x+=inf*dx[k];
      q[m].y+=inf*dy[k];
      return 2;
    }
    inline void adda(const P&A,const P&B){
      if(A.y!=B.y)return;
      ll l=A.x,r=B.x;
      if(l>r)swap(l,r);
      l++,r--;
      if(l>r)return;
      e[++ce]=E(l,A.y,0,1);
      e[++ce]=E(r,A.y,0,-1);
      f[++cf]=A.y;
    }
    inline void addb(const P&A,const P&B){
      if(A.x!=B.x)return;
      ll l=A.y,r=B.y;
      if(l>r)swap(l,r);
      l++,r--;
      if(l>r)return;
      e[++ce]=E(A.x,l,r,0);
      f[++cf]=l,f[++cf]=r;
    }
    inline int lower(ll x){
      int l=1,r=cf,mid,t;
      while(l<=r)if(f[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline void add(int x,int p){for(;x<=cf;x+=x&-x)bit[x]+=p;}
    inline int ask(int x){int t=0;for(;x;x-=x&-x)t+=bit[x];return t;}
    ll cal(){
      int i;
      sort(f+1,f+cf+1);
      for(i=1;i<=cf;i++)bit[i]=0;
      sort(e+1,e+ce+1,cmpe);
      ll ret=0;
      for(i=1;i<=ce;i++)if(e[i].t)add(lower(e[i].l),e[i].t);else ret+=ask(lower(e[i].r))-ask(lower(e[i].l)-1);
      return ret;
    }
    ll solve(int x){
      int i;
      ce=cf=0;
      for(i=1;i<cb;i++)adda(b[i],b[i+1]);
      for(i=3-x;i<cc;i++)addb(c[i],c[i+1]);
      ll ret=cal();
      ce=cf=0;
      for(i=1;i<cb;i++)addb(b[i],b[i+1]);
      for(i=3-x;i<cc;i++)adda(c[i],c[i+1]);
      return ret+cal();
    }
    int main(){
      read(n);
      B.read();
      for(i=1;i<=n;i++){
        char c[9];
        a[i].read();
        scanf("%s",c);
        d[i]=c[0];
        q[i]=i;
      }
      sort(q,q+n+1,cmpx);
      for(i=0;i<=n;i++)for(j=0;j<4;j++)g[i][j]=-1;
      for(i=0;i<=n;){
        for(j=i;j<=n&&a[q[i]].x==a[q[j]].x;j++);
        for(i++;i<j;i++){
          g[q[i]][0]=q[i-1];
          g[q[i-1]][1]=q[i];
        }
      }
      sort(q,q+n+1,cmpy);
      for(i=0;i<=n;){
        for(j=i;j<=n&&a[q[i]].y==a[q[j]].y;j++);
        for(i++;i<j;i++){
          g[q[i]][2]=q[i-1];
          g[q[i-1]][3]=q[i];
        }
      }
      work(P(0,0),1,b,cb);
      for(i=0;i<4;i++){
        int x=work(B,i,c,cc);
        ans+=solve(x)*x;
      }
      return printf("%lld",ans/2),0;
    }
    

      

  • 相关阅读:
    RedHat 更新CentOS Yum源(转)
    ubuntu 印象笔记
    (转)FFMPEG filter使用实例(实现视频缩放,裁剪,水印等)
    (转)学习ffmpeg官方示例transcoding.c遇到的问题和解决方法
    源码调用ffmpeg库时,需要注意接口为C接口
    codeforces 722D Generating Sets 【优先队列】
    poj2970 The lazy programmer 【优先队列】
    codeblocks17.12 不能启动调试器
    Unity动画知识之二:Animator动画状态机
    关于unity里pbr技术和材质 unity5默认shader和传统的对比
  • 原文地址:https://www.cnblogs.com/clrs97/p/7487885.html
Copyright © 2011-2022 走看看