CF2096D题解

CF2096D 题解

题意忘了就点进 CF 里面看,总之就是非常人类智慧。

分析

没有任何头绪,甚至搜索都没办法写。就像求积分一样,你可以很轻松地从 \(A\)\(B\),但是从 \(B\)\(A\) 却是一个非常 NP 的过程,这种问题通常都是无从下手的,也只能说做一道积累一道的经验。
这种异或门开关无非就是涉及到奇偶性,考虑一开始的图只有一个点,也就是我们要求的点 \((s,t)\),那么整个坐标系的所有竖直直线中,只有 \(x=s\) 这一条上面有奇数个点。这时如果我们对任意位置进行操作,这个性质会改变吗?分类讨论一下发现是不会的,所以这个横坐标 \(s\) 和点的奇偶个数就变成了一个充要关系。我们在读入的时候用 map 记录每个坐标上面的点的个数,最后遍历一下这个 map,发现奇数个的时候,说明这时一定有 \(x=s\)

那如何确定 \(t\)?发现如果延用上述思路去对 \(y\) 坐标对应直线上点的个数进行讨论,就没有这样的“充要性质”了。为什么呢?回到确定 \(s\) 的时候的方法的本质,其实是我们每次操作对于 \(x=c\) 的直线都只会引入偶数个点,但是对于 \(y=c\) 就不再有这样的性质了。没关系,换个角度看,就又有这个性质了————从 \(y=-x+c\) 的方向看,每次操作同样只会引入偶数个点。于是我们对 \(x+y\) 的值如法炮制,就能够求出 \(s+t\) 了。

从而,我们分别得到了 \(s,t\) 的值。

Code

#include<bits/stdc++.h>
using namespace std;

map<int,int> cor,cor1;

inline void solve()
{
    cor.clear(),cor1.clear();
    int n;
    cin>>n;
    int x,y;
    for(int i=1;i<=n;++i)
    {
        cin>>x>>y;
        cor[x]++;
        cor1[x+y]++;
    }
    int s,t;
    for(auto it:cor)
    {
        if(it.second&1)
        {
            s=it.first;
            break;
        }
    }
    for(auto it:cor1)
    {
        if(it.second&1)
        {
            t=it.first-s;
            break;
        }
    }
    cout<<s<<" "<<t<<'\n';
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int T;cin>>T;
    while(T--)solve();
    return 0;
}
posted @ 2025-04-27 10:45  Hanggoash  阅读(52)  评论(0)    收藏  举报
动态线条
动态线条end