• BZOJ3592 : Architext


    首先特判多边形面积$=0$的情况,此时内部没有点,答案只会在顶点处取到。

    对于面积$>0$的情况,离线询问,将所有多边形合在一起得到平面图,然后求出对偶图,那么每条多边形边的两侧分别对应对偶图中两个域。

    每个多边形把这些域分成内外两个连通块,也就是保留除了多边形边之外的所有边后对偶图的连通情况。

    把每个点随便放在所在的某个域之中,按时间分治,维护按秩合并的并查集。

    对于每个询问任取一条多边形边,它两侧分别是域$A$和域$B$。那么有且仅有一个不与无穷域连通,假设是$A$,那么答案就是$A$所在连通块的信息。这会漏掉一些因为随便指派而不在连通块内的顶点。遍历每个顶点$x$,判断$x$所在域所在连通块是否和无穷域连通,是的话再把$x$的信息加入答案即可。

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

    #include<cstdio>
    #include<cmath>
    #include<set>
    #include<algorithm>
    #include<map>
    #include<vector>
    using namespace std;
    typedef pair<int,int>PI;
    typedef long long ll;
    const int N=50010,M=320010;
    int Case,n,m,cq,cnt,i,j,k,x,y,z,q[N],at[N];
    map<PI,int>idx;
    int que[N][3];
    vector<int>pool[N];
    int dep[M],f[M],sum[M],mx[M],val[N];
    int laste[M],lastv[N];
    int co,op[N*3+M*2][3];
    int MX,SUM;
    struct EV{
      char op;int x,y,l,r;
      EV(){}
      EV(char _op,int _x,int _y,int _l,int _r){op=_op,x=_x,y=_y,l=_l,r=_r;}
    };
    typedef vector<EV>V;
    struct P{
      int x,y,d;
      ll operator*(const P&b){return 1LL*x*b.y-1LL*y*b.x;}
    }a[N];
    struct E{
      int x,y;double o;
      E(){}
      E(int _x,int _y){x=_x,y=_y,o=atan2(a[y].x-a[x].x,a[y].y-a[x].y);}
    }e[M];
    bool del[M];int from[M];
    namespace GetArea{
    struct cmp{bool operator()(int a,int b){return e[a].o<e[b].o;}};
    set<int,cmp>g[N];set<int,cmp>::iterator k;int i,j,q[M],t;
    void work(){
      for(i=0;i<m+m;i++)if(!del[i]){
        for(q[t=1]=j=i;;q[++t]=j=*k){
          k=g[e[j].y].find(j^1);k++;
          if(k==g[e[j].y].end())k=g[e[j].y].begin();
          if(*k==i)break;
        }
        ll s=0;
        for(j=1;j<=t;j++)s+=a[e[q[j]].x]*a[e[q[j]].y],del[q[j]]=1;
        if(s<=0)continue;
        for(cnt++,j=1;j<=t;j++){
          from[q[j]]=cnt;
          at[e[q[j]].x]=at[e[q[j]].y]=cnt;
        }
      }
    }
    }
    inline void newedge(int x,int y){
      if(idx.find(PI(x,y))!=idx.end())return;
      if(idx.find(PI(y,x))!=idx.end())return;
      e[m<<1]=E(x,y);
      e[m<<1|1]=E(y,x);
      idx[PI(x,y)]=idx[PI(y,x)]=m++;
    }
    inline int getid(int x,int y){return idx[PI(x,y)];}
    int F(int x){return f[x]==x?x:F(f[x]);}
    inline void merge(int x,int y){
      x=F(x),y=F(y);
      if(x==y)return;
      if(dep[x]==dep[y]){
        co++;
        op[co][0]='d';
        op[co][1]=x;
        dep[x]++;
      }
      if(dep[x]<dep[y])swap(x,y);
      co++;
      op[co][0]='f';
      op[co][1]=y;
      f[y]=x;
      if(mx[y]>mx[x]){
        co++;
        op[co][0]='m';
        op[co][1]=x;
        op[co][2]=mx[x];
        mx[x]=mx[y];
      }
      co++;
      op[co][0]='s';
      op[co][1]=x;
      op[co][2]=sum[y];
      sum[x]+=sum[y];
    }
    inline void ins(int x,int y){
      int z=F(at[x]);
      co++;
      op[co][0]='v';
      op[co][1]=x;
      op[co][2]=val[x];
      val[x]=y;
      if(y>mx[z]){
        co++;
        op[co][0]='m';
        op[co][1]=z;
        op[co][2]=mx[z];
        mx[z]=y;
      }
      co++;
      op[co][0]='s';
      op[co][1]=z;
      op[co][2]=y;
      sum[z]+=y;
    }
    inline void retrace(int t){
      while(co>t){
        if(op[co][0]=='d')dep[op[co][1]]--;
        else if(op[co][0]=='f')f[op[co][1]]=op[co][1];
        else if(op[co][0]=='v')val[op[co][1]]=op[co][2];
        else if(op[co][0]=='m')mx[op[co][1]]=op[co][2];
        else sum[op[co][1]]-=op[co][2];
        co--;
      }
    }
    inline void up(int&a,int b){a<b?(a=b):0;}
    void solve(int l,int r,V v){
      int pos=co,mid=(l+r)>>1;
      V vl,vr;
      for(V::iterator it=v.begin();it!=v.end();it++){
        if(it->l<=l&&r<=it->r){
          if(it->op=='E')merge(it->x,it->y);
          else ins(it->x,it->y);
        }else{
          if(it->l<=mid)vl.push_back(*it);
          if(it->r>mid)vr.push_back(*it);
        }
      }
      if(l==r){
        if(que[l][0]==1){
          int j,o,u,k=que[l][1];
          for(j=0;j<k;j++)q[j]=pool[l][j];
          q[k]=q[0];
          MX=SUM=0;
          if(que[l][2]){
            for(j=0;j<k;j++){
              o=q[j];
              SUM+=val[o];
              up(MX,val[o]);
            }
          }else{
            o=getid(q[0],q[1])<<1;
            u=from[o];
            if(F(u)==F(0))u=from[o|1];
            u=F(u);
            SUM=sum[u];
            MX=mx[u];
            for(j=0;j<k;j++){
              o=q[j];
              if(F(at[o])!=u){
                SUM+=val[o];
                up(MX,val[o]);
              }
            }
          }
          printf("%d %d
    ",SUM,MX);
        }
        retrace(pos);
        return;
      }
      solve(l,mid,vl);
      solve(mid+1,r,vr);
      retrace(pos);
    }
    int main(){
      scanf("%d%d",&Case,&n);
      for(i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
      scanf("%d",&cq);
      if(!cq)return 0;
      for(i=1;i<=cq;i++){
        char op[5];
        scanf("%s",op);
        if(op[0]=='H')scanf("%d%d",&que[i][1],&que[i][2]);
        else{
          que[i][0]=1;
          scanf("%d",&k);
          que[i][1]=k;
          for(j=0;j<k;j++)scanf("%d",&q[j]);
          q[k]=q[0];
          for(j=0;j<k;j++)newedge(q[j],q[j+1]);
          pool[i].resize(k);
          for(j=0;j<k;j++)pool[i][j]=q[j];
        }
      }
      for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i);
      GetArea::work();
      V v;
      for(i=1;i<=n;i++)lastv[i]=1;
      for(i=1;i<=cq;i++){
        if(que[i][0]==0){
          x=que[i][1];
          y=lastv[x];
          if(y<=i-1)v.push_back(EV('V',x,a[x].d,y,i-1));
          a[x].d+=que[i][2];
          lastv[x]=i;
        }else{
          k=que[i][1];
          for(j=0;j<k;j++)q[j]=pool[i][j];
          q[k]=q[0];
          ll s=0;
          for(j=0;j<k;j++)s+=a[q[j]]*a[q[j+1]];
          if(s<0){
            for(j=0;j<k;j++){
              x=getid(q[j],q[j+1]);
              y=laste[x];
              if(y+1<=i-1)v.push_back(EV('E',from[x<<1],from[x<<1|1],y+1,i-1));
              laste[x]=i;
            }
          }else que[i][2]=1;
        }
      }
      for(i=1;i<=n;i++)v.push_back(EV('V',i,a[i].d,lastv[i],cq));
      for(i=0;i<=cnt;i++)f[i]=i;
      for(i=0;i<m;i++){
        y=laste[i];
        if(y+1<=cq)v.push_back(EV('E',from[i<<1],from[i<<1|1],y+1,cq));
      }
      solve(1,cq,v);
      return 0;
    }
    

      

  • 相关阅读:
    go字面量常量
    go ssh开箱即用,注意几点
    dtle 3.x数据同步
    大厂晋升指南:材料准备,PPT 写作和现场答辩
    电商广告营销中,有哪些常见公式和优化手段?
    用Turkle库和OpenCV图像识别画一个冰墩墩
    gRPC in ASP.NET Core 3.x Protocol Buffer(3)更新消息类型 yangxu
    Rust 使用 dotenv 来设置环境变量 yangxu
    以正确的方式下载和配置 ASP.NET Core 官方源码 yangxu
    ASPOSE.Cells & ASPOSE.Words 操纵Excel和Word文档的 .NET Core 实例 yangxu
  • 原文地址:https://www.cnblogs.com/clrs97/p/10410017.html
Copyright © 2020-2023  润新知