ZigZagK的博客
[几何+复杂度分析]Codeforces1028F【Make Symmetrical】题解
2018年9月2日 16:15
查看标签

题目概述

有 $q$ 次操作,每次操作:1.加入一个整点。2.删除一个整点。3.询问以一条 $y\over x$ 为斜率过原点的线为对称轴,需要添加多少个点使得所有点都有对称点。

解题报告

一直在推式子……发现考虑下几何意义(看下题解和AC代码)就行了……如果两个点 $(x_1,y_1),(x_2,y_2)$ 与原点的距离相同,那么这两个点的连线就是他们对称轴的中垂线。

记 $S(l)$ 表示以 $l$ 为对称轴配对点的个数,也就是说 $(x_1,y_1),(x_2,y_2),x_1^2+y_1^2=x_2^2+y_2^2$ 对 $S({y_1+y_2\over x_1+x_2})$ 有贡献。

因为可以爆枚发现 $x^2+y^2=A$ 的解在 $A\le 10^{10}$ 的情况下最多只有 $O(100)$ 组解,所以复杂度是正常的。

再记录 $L(l)$ 表示在 $l$ 上的点的个数,每次询问的答案就是 $n-2S(l)-L(l)​$ 。

示例程序

吃我mapset树套树。

#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#define fr first
#define sc second
#define mp make_pair
using namespace std;
typedef long long LL;typedef pair<int,int> data;

int te,n;map<data,int> L,S;map<LL, set<data> > P;set<data>::iterator it;

int gcd(int a,int b) {return b?gcd(b,a%b):a;}
inline data Line(int x,int y) {int t=gcd(x,y);return mp(x/t,y/t);}
int main(){
    freopen("program.in","r",stdin);freopen("program.out","w",stdout);
    for (int td=scanf("%d",&te),x,y;te;te--){
        scanf("%d%d%d",&td,&x,&y);LL val=(LL)x*x+(LL)y*y;
        if (td==1){
            for (it=P[val].begin();it!=P[val].end();it++) S[Line((*it).fr+x,(*it).sc+y)]++;
            L[Line(x,y)]++;P[val].insert(mp(x,y));n++;
        } else if (td==2) {
            L[Line(x,y)]--;P[val].erase(mp(x,y));n--;
            for (it=P[val].begin();it!=P[val].end();it++) S[Line((*it).fr+x,(*it).sc+y)]--;
        } else printf("%d\n",n-L[Line(x,y)]-2*S[Line(x,y)]);
    }
    return 0;
}
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处!