zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    thinkphp5 tp5 命名空间 报错 Namespace declaration statement has to be the very first statement in the script
    开启 php 错误 提示 php-fpm 重启 nginx 500错误 解决办法 wdlinux lnmp 一键包 php脚本无法解析执行
    js 设置 cookie 定时 弹出层 提示层 下次访问 不再显示 弹窗 getCookie setCookie setTimeout
    php 二维数组 转字符串 implode 方便 mysql in 查询
    nginx 重启 ps -ef|grep nginx kill -HUP 主进程号
    jquery bootstrap help-block input 表单 提示 帮助 信息
    jquery 倒计时 60秒 短信 验证码 js ajax 获取
    jQuery如何获取同一个类标签的所有的值 遍历
    linux下C语言文件操作相关函数
    gcc,gdb用法
  • 原文地址:https://www.cnblogs.com/clrs97/p/10410017.html
Copyright © 2011-2022 走看看