版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/82142380
题意
给一个无限大的二维平面, 次操作,(1)在平面上加一个点(保证加入前不存在),(2)在平面上删除一个点(保证删除时存在),(3)给出一个点,以原点和这个点连成的直线为对称轴,问你至少要加几个点可以使得这个平面对称。
分析
首先我们猜一个结论,就是一个以原点为圆心的圆上的整点是不会很多的(具体我不会证)。然后又因为如果这个平面对称,那么两个对称点到原点的距离肯定是相等的。那么我们每次加入或删除一个点时,记这个点到原点的距离为 ,那我们暴力枚举这个以 为半径,原点为圆心的圆上其他的点,算出他们的对称轴,把这个对称轴的数值加上或减去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]);
}
}