AIM Tech Round 5 (rated, Div. 1 + Div. 2)F. Make Symmetrical(结论+暴力)

版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/82142380

题意

  给一个无限大的二维平面, n ( n 2 10 5 ) 次操作,(1)在平面上加一个点(保证加入前不存在),(2)在平面上删除一个点(保证删除时存在),(3)给出一个点,以原点和这个点连成的直线为对称轴,问你至少要加几个点可以使得这个平面对称。

分析

  首先我们猜一个结论,就是一个以原点为圆心的圆上的整点是不会很多的(具体我不会证)。然后又因为如果这个平面对称,那么两个对称点到原点的距离肯定是相等的。那么我们每次加入或删除一个点时,记这个点到原点的距离为 d ,那我们暴力枚举这个以 d 为半径,原点为圆心的圆上其他的点,算出他们的对称轴,把这个对称轴的数值加上或减去2,然后把这个点和原点连成的直线所形成的对称轴的数值加上或减去1,之后每次O(1)回答答案就行了。

Code

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
struct Point {
    int x,y;
    Point(int _x=0,int _y=0) {
        x=_x,y=_y;
    }
    inline bool operator < (const Point &rhs) const {
        return x==rhs.x?y<rhs.y:x<rhs.x;
    }
    inline Point F() {
        Point p=Point(x,y);
        if(x||y) {
            int g=__gcd(p.x,p.y);
            p.x/=g,p.y/=g;
        }
        return p;
    }
    inline Point operator + (const Point &rhs) const {
        return Point(x+rhs.x,y+rhs.y).F();
    }
};
int n,cnt;
map<ll,set<Point> >circle;
map<Point,int>exist;
Point o(0,0);
int main() {
    read(n);
    while(n--) {
        int ty,x,y;
        read(ty),read(x),read(y);
        Point t=Point(x,y);
        ll d=1ll*x*x+1ll*y*y;
        if(ty==1) {
            for(auto p:circle[d])
                exist[p+t]+=2;
            circle[d].insert(t);
            exist[o+t]++,cnt++;
        }
        if(ty==2) {
            circle[d].erase(circle[d].find(t));
            for(auto p:circle[d])
                exist[p+t]-=2;
            exist[o+t]--,cnt--;
        }
        if(ty==3)
            printf("%d\n",cnt-exist[o+t]);
    }
}

猜你喜欢

转载自blog.csdn.net/Effervescence/article/details/82142380