• 计算几何小结


    计算几何小结!

    零,说在前面

    (转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/8379553.html )

    这次总结的是计算几何!

    根据学长们的观点,计算几何是一类0or100的题目

    但是事实上,计算几何题目很考验码力和细节处理能力,以及数学上平几和立体几何那堆东西……

    我个人觉得这样的题目是对个人很好的锻炼,虽然我考场上还是只能打暴力罢了2333

    那么我们开始总结吧!

    一,凸包

    这大概是我们的万恶之源了……这里我把之前的凸包总结搬过来

    然后续写两句现在的理解

    凸包其实是一种最优化的体现,它通过把处理的对象从全集减少到一些“更可能成为最优答案”的点上,从而使我们能更快得到答案

    这点尤为体现在DP的斜率优化上

    当然,凸包也在数学和几何方面毒瘤着发挥着作用,也有很多巧妙的题目,比如上面那道uoj243破坏导蛋的处理,那个是我的确没有想到的

    当然也有关于凸包的很多算法,但是维护凸包的算法只是工具,重要的还是凸包体现的最优化思想

    我觉得在我做过的凸包的题里面给我印象最深的就是uoj319分身术了

    充分的利用了题目k比较小的条件,维护了子区间的凸包并且合并,从而支持了快速查询

    这是我自从联赛前打模拟题(杀蚂蚁等等)以来打过的最考码力的一道题,打完之后的确感觉码力得到提升2333虽然现在还是咸鱼的打不出来

    然而如果考出来还是只能打暴力……

    二,旋转卡壳

    施工ing……

    三,半平面交

    这玩意其实和高考数学的线性规划是一个东西……

    以前的总结正在补……

    先写下最近做的题目……

      UOJ#242 破坏蛋糕

        施工ing……

      UOJ#243 破坏导蛋

        题意很简洁,但是很巧妙也很难想

        我自己能想出加起来总共70pts……

        前20pts暴力不用说啦……

        中间有20pts坐标范围很小,我们可以维护每个x坐标y的前缀和,然后对于每次询问暴力查询

        这样的复杂度是$O(n+200^{2}+200m)$的,可以通过那部分数据

        然后后面有一个很多直线平行的部分分,我觉得可以对于每种直线,维护每个点ax+by的值,然后查询……

        这个东西应该可以搞个分块维护下,块内存个排序,整块用二分,散点暴力

        这样加起来是70pts

        后面的我还不会做,正在想……

        我们还是怂题解吧,这个太巧妙了

        我们上面那个维护查询的问题是每一种ax+by都要处理一次,但是我们可以发现对于某两个点,他们只会在特定的(a,b)处相等

        这样,不同的序列只有$O(n^{2})$级别

        然后我们考虑分块跑这个$n^2$,然后维护一个bitset表示合法

        ……操作很辣眼睛,我只能将近看懂jiry的标程

        啊……我把带注释的std存在这……

      1 #include <iostream>
      2 #include <cmath>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <cstring>
      6 #include <bitset>
      7 using namespace std;
      8 #define LL long long
      9 
     10 const int size=200;
     11 struct point
     12 {
     13     int x,y;
     14     double getw(int flag=0)
     15     {
     16         if (flag) return atan2(-y,x);
     17         return atan2(y,x);
     18     }
     19     void scan(){scanf("%d%d",&x,&y);}
     20 
     21 }A[51000],B[size+10],f[size+10];
     22 
     23 point operator - (point k1,point k2) {return (point){k1.x-k2.x,k1.y-k2.y};}
     24 int n,N,m,ans[110000],a[size+10],where[size+10],wa,wb;
     25 double w[size+10];
     26 bitset<size+10>an[110010],C[size+10],tot;
     27 struct ask
     28 {
     29     int a,b,where;
     30     LL c;
     31     double w;
     32     void set(point k1,point k2)
     33         {a=k2.y-k1.y,b=-(k2.x-k1.x),c=-((LL)k1.x*a+(LL)k1.y*b),w=atan2(a,b);}
     34 
     35     int pd(point k1){return (LL)k1.x*a+(LL)k1.y*b+c<=0;}
     36 
     37     void rev(){a=-a,b=-b,c=-c,w=atan2(a,b);}
     38 }x[310000];
     39 
     40 int compare(ask k1,ask k2){return k1.w<k2.w;}
     41 
     42 int compare2(int k1,int k2){return w[k1]<w[k2];}
     43 
     44 const double pi=acos(-1);
     45 
     46 int compare3(int k1,int k2)//comp ax+by
     47     {return (LL)B[k1].x*wa+(LL)B[k1].y*wb<(LL)B[k2].x*wa+(LL)B[k2].y*wb;}
     48 
     49 struct atom{int u,v;double w;}y[110000];
     50 
     51 int len;
     52 
     53 LL k1xk2(point k1,point k2){return (LL)k1.x*k2.y-(LL)k1.y*k2.x;}
     54 
     55 int compare4(const atom &k1,const atom &k2){return k1.w<k2.w;}
     56 
     57 int check(atom k1,atom k2)//两向量平行
     58 {
     59     point a=B[k1.v]-B[k1.u],b=B[k2.v]-B[k2.u];
     60     return k1xk2(a,b)==0&&(LL)a.x*b.x>=0&&(LL)a.y*b.y>=0;
     61 }
     62 
     63 int check(point k1,point k2)//相当于上面的comp3,比较了ax+by
     64     {return (LL)k1.x*wa+(LL)k1.y*wb<(LL)k2.x*wa+(LL)k2.y*wb;}
     65 
     66 void gopre(int k)//由于a和b的更改带来的顺序更改
     67 {
     68     while ( where[k]>1 &&check( B[k],B[ a[where[k]-1] ]  ))
     69     {
     70         int k1=where[k],k2=a[k1-1];
     71         swap(a[k1],a[k1-1]);
     72         swap(f[k1],f[k1-1]);
     73         C[k1-1][k]=1; C[k1-1][k2]=0;
     74         where[k]--; where[k2]++;
     75     }
     76 }
     77 void getw(int k1)
     78 {
     79     int l=1,r=n+1,ans=n+1;
     80     LL aa=x[k1].a,b=x[k1].b,c=x[k1].c;
     81     while (l<r)
     82     {
     83         int mid=(l+r)>>1;
     84         if(aa*f[mid].x+b*f[mid].y+c<=0)l=mid+1;
     85         else ans=mid,r=mid;
     86     }
     87     an[x[k1].id]&=C[ans-1]; 
     88 }
     89 
     90 
     91 int sign,pd[size+10],s[size+10],head;
     92 void insert(int k1)
     93 {
     94     if (pd[k1]!=sign)
     95         pd[k1]=sign,s[++head]=k1;
     96 }
     97 
     98 
     99 void solve(){
    100     memset(an,0x00,sizeof an);
    101 
    102     tot=0; 
    103     for(int i=1;i<=n;i++)tot[i]=1;
    104     for (int i=1;i<=m/3;i++)an[i]=tot;
    105     wa=0; wb=-1;
    106 
    107     for (int i=1;i<=n;i++)a[i]=i;
    108     sort(a+1,a+n+1,compare3);//comp ax+by
    109     for (int i=1;i<=n;i++)//记录每个点现在的排名,然后f是排序后的结果
    110         where[a[i]]=i,f[i]=B[a[i]];
    111     for (int i=1;i<=n;i++)//C是点集前缀和
    112         C[i]=C[i-1],C[i][a[i]]=1;
    113     
    114     len=0;
    115     for(int i=1;i<=n;i++)
    116         for(int j=1;j<=n;j++)
    117             if(i^j)//由j指向i的向量,包括id以及……极角?这个极角是什么操作?
    118                 //这大概就是题解中所说的关键点吧……
    119                 //如果按照我昨天推的转化式子这玩意是对的,a等于-y,b等于x
    120             {
    121                 y[++len]=(atom){  j,i,(B[i]-B[j]).getw(1)  };
    122                 if(B[i].y==B[j].y)
    123                 {
    124                     if(B[j].x>B[i].x)y[len].w=-pi;
    125                     else y[len].w=0;
    126                 }
    127             }
    128     sort(y+1,y+len+1,compare4);//按极角排序?
    129     int pre=1,now=1; y[len+1].w=pi;
    130     for (int i=1;i<=len+1;i++)
    131     {
    132         while(now<=m&&x[now].w<=y[i].w)getw(now++);
    133         //还没达到下一个关键点,现在可以更新答案
    134         if ( ( i!=len+1  &&  check(y[i],y[i+1])==0    )  || i==len )
    135         {//到达关键点(与下一个不平行)
    136             wa=-(B[y[i].v].y-B[y[i].u].y);
    137             wb=B[y[i].v].x-B[y[i].u].x;
    138             //
    139             point pre1=(point){wa,wb};
    140             if(i==len)wb--;//进行一些偏移
    141 
    142             else 
    143                 wa-=B[y[i+1].v].y-B[y[i+1].u].y,
    144                 wb+=B[y[i+1].v].x-B[y[i+1].u].x;
    145             if(k1xk2(pre1,(point){wa,wb})==0)//共线?刚才不是判了么?
    146                 wa=pre1.y,wb=-pre1.x;
    147 
    148             head=0;sign++; 
    149             for (int j=pre;j<=i;j++)
    150                 insert(where[y[j].u]),insert(where[y[j].v]);
    151             //插入这段时间内新的点
    152             sort(s+1,s+head+1);
    153             for (int j=1;j<=head;j++)//进行交换
    154                 gopre(a[s[j]]);
    155             pre=i+1;
    156         }
    157     }
    158     for (int i=1;i<=m/3;i++) ans[i]+=an[i].count();
    159 }
    160 int main(){
    161 
    162 
    163 
    164     scanf("%d%d",&N,&m); 
    165     for (int i=1;i<=N;i++) A[i].scan();
    166     for (int i=1;i<=m;i++){
    167         point k1,k2,k3; k1.scan(); k2.scan(); k3.scan();
    168         x[i*3-2].set(k1,k2);
    169         x[i*3-1].set(k2,k3);
    170         x[i*3].set(k3,k1);
    171         if (x[i*3-2].pd(k3)==0) x[i*3-2].rev();
    172         if (x[i*3-1].pd(k1)==0) x[i*3-1].rev();
    173         if (x[i*3].pd(k2)==0) x[i*3].rev();
    174     }
    175 
    176 
    177 
    178     m*=3;
    179     for (int i=1;i<=m;i++) x[i].id=(i-1)/3+1;
    180     sort(x+1,x+m+1,compare);
    181     for (int l=1;l<=N;l+=size)
    182     {
    183         int r=min(N,l+size-1);
    184         n=r-l+1;
    185         for(int i=l;i<=r;i++)
    186             B[i-l+1]=A[i];
    187         solve();
    188     }
    189     m/=3;
    190     for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    191     return 0;
    192 }
    UOJ#243std

        

    四,Simpson积分

    施工ing……

    五,没做两道题的其他专题

      一,平面图转对偶图

        施工ing……

      二,随机化算法

        1.最小圆覆盖

        施工ing……

      三,三维几何

        施工ing……

    六,总结

    施工ing……

  • 相关阅读:
    数据结构与算法----双向链表
    数据结构与算法----数学应用之一元多项式
    数据结构----线性表顺序和链式结构的使用(c)
    Android--Otto事件总线 -- 组件之间通讯框架使用 --模式解析
    递归 —— 二分查找法 —— 归并排序
    自己做悬浮拖拽按钮依赖
    RePlugin 插件化-内置加载
    Android图片处理--缩放
    数据结构与算法---常用三大排序算法
    Android图片处理--全景查看效果
  • 原文地址:https://www.cnblogs.com/LadyLex/p/8379553.html
Copyright © 2020-2023  润新知