zoukankan      html  css  js  c++  java
  • cf 975E

    出于某种不可抗力我翻了一下以前绿名时打的div2,然后插旗:这种傻逼div2我现在不是随手ak吗? 然后就没有然后了
    给一个凸包,一开始固定两个点,每次拆下一个点(取消固定),待稳定后再固定另外一个点。
    支持查询第几个点的坐标。
    首先求凸包重心,全部划分成三角形那样子。
    考虑一次旋转操作,其实是将重心旋转到了固定点的正下方。
    那么在知道了每个点相对于重心的向量后,这其实蛮好求的。
    同样,重心每次旋转的角度也容易知道。
    所以我们翻过来考虑,维护重心坐标和旋转角度,对于一个查询,我们用它的相对位置*角度+重心即可。
    很好的一道题。
    有点神志不清调了好久

    #include <bits/stdc++.h>
    #define mp make_pair
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    typedef double db;
    const db eps=1e-6;
    const db pi=acos(-1);
    int sign(db k){
        if (k>eps) return 1; else if (k<-eps) return -1; return 0;
    }
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
    struct point{
        db x,y;
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
        point operator * (db k1) const{return (point){x*k1,y*k1};}
        point operator / (db k1) const{return (point){x/k1,y/k1};}
        int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
        // 逆时针旋转
        point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
        point turn90(){return (point){-y,x};}
        bool operator < (const point k1) const{
            int a=cmp(x,k1.x);
            if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
        }
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
        point unit(){db w=abs(); return (point){x/w,y/w};}
        void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;}
        void print(){printf("%.11lf %.11lf
    ",x,y);}
        db getw(){return atan2(y,x);}
        point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
        int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
    };
    int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
    db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
    db rad(point k1,point k2){return atan2(cross(k1,k2),dot(k1,k2));}
    // -pi -> pi
    int compareangle (point k1,point k2){//极角排序+
        return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>0);
    }
    point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
        point k=k2-k1;return k1+k*(dot(q-k1,k)/k.abs2());
    }
    point reflect(point k1,point k2,point q){return proj(k1,k2,q)*2-q;}
    int clockwise(point k1,point k2,point k3){// k1 k2 k3 逆时针 1 顺时针 -1 否则 0
        return sign(cross(k2-k1,k3-k1));
    }
    int checkLL(point k1,point k2,point k3,point k4){// 求直线 (L) 线段 (S)k1,k2 和 k3,k4 的交点
        return cmp(cross(k3-k1,k4-k1),cross(k3-k2,k4-k2))!=0;
    }
    point getLL(point k1,point k2,point k3,point k4){
        db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2);
    }
    int intersect(db l1,db r1,db l2,db r2){
        if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
    }
    int checkSS(point k1,point k2,point k3,point k4){
        return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
               sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
               sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
    }
    db disSP(point k1,point k2,point q){
        point k3=proj(k1,k2,q);
        if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
    }
    db disSS(point k1,point k2,point k3,point k4){
        if (checkSS(k1,k2,k3,k4)) return 0;
        else return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2)));
    }
    int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
    point Centroid(vector<point> v){
        point ans={0,0};db S=0;
        for(int i=1;i<v.size()-1;i++){
            db s = fabs(cross(v[i]-v[0],v[i+1]-v[0]));
            ans = ans+(v[0]+v[i]+v[i+1])*s/3;
            S+=s;
        }
        //S!=0
        return ans/S;
    }
    struct circle{
        point o; db r;
        void scan(){o.scan(); scanf("%lf",&r);}
        int inside(point k){return cmp(r,o.dis(k));}
    };
    struct line{
        // p[0]->p[1]
        point p[2];
        line(point k1,point k2){p[0]=k1; p[1]=k2;}
        point& operator [] (int k){return p[k];}
        int include(point k){return sign(cross(p[1]-p[0],k-p[0]))>0;}
        point dir(){return p[1]-p[0];}
        line push(){ // 向外 ( 左手边 ) 平移 eps
            const db eps = 1e-6;
            point delta=(p[1]-p[0]).turn90().unit()*eps;
            return {p[0]-delta,p[1]-delta};
        }
    };
    point getLL(line k1,line k2){return getLL(k1[0],k1[1],k2[0],k2[1]);}
    int n,q,b[10005];
    vector<point> p;point o;
    db ang=0;
    int main(){
        scanf("%d%d",&n,&q);
        p.resize(n);
        for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
        o=Centroid(p);
    //    o.print();
        for(int i=0;i<n;i++)p[i]=p[i]-o;
        int op,f,t,a1=0,a2=1;b[0]=b[1]=1;
        while (q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d",&f,&t);
                f--;t--;
                b[f]--;
                if(b[f]==0){
                    int otr = (f==a1?a2:a1);
                    point tmp = o+p[otr].turn(ang);//旋转点
    //                tmp.print();
                    db jiao = rad(o-tmp,point{0,-1.0});
    //                printf("%.11f
    ",jiao);
    //                printf("%.11f
    ",p[otr].abs());
                    o=tmp+(point){0,-1.0}*p[otr].abs();
                    ang+=jiao;
                }
    //            o.print();
                b[t]++;
                if(f==a1)a1=t;else a2=t;
            }else{
                scanf("%d",&f);
                f--;
                point tmp=o+p[f].turn(ang);
                tmp.print();
            }
        }
    }
    
  • 相关阅读:
    Android(java)学习笔记68:使用proguard混淆android代码
    SGU 194 Reactor Cooling
    关于流量有上下界的网络流问题的求解
    关于最小割的求解方法
    HDU 5311 Hidden String
    POJ 3548 Restoring the digits
    POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater
    ZOJ 1967 POJ 2570 Fiber Network
    HDU 1969 Pie
    HDU 1956 POJ 1637 Sightseeing tour
  • 原文地址:https://www.cnblogs.com/MXang/p/11343551.html
Copyright © 2011-2022 走看看