A. 小红的直角三角形

显然两个点一个在 轴上,另一个在 轴上时满足条件。

时间复杂度

a,b,c,d=map(int,input().split())
if (a==0 and d== 0) or (c==0 and b==0):
    print("Yes")
else:
    print("No")

B.小红的好点对

对每个点检查四个方向有没有点即可,最后答案再除 去掉重复统计。

时间复杂度

也可以遍历每个点对,检查距离是否为

时间复杂度

# O(n)
n = int(input())
p = [list(map(int, input().split())) for i in range(n)]
memo = {tuple(i) for i in p}
ans = 0
for x, y in p:
    for dx, dy in [[1, 0],[-1, 0], [0, 1], [0, -1]]:
        if (x+dx, y+dy) in memo:
            ans += 1
print(ans//2)
# O(n^2)
n = int(input())
p = [list(map(int, input().split())) for i in range(n)]
ans = 0
for i in range(n):
    for j in range(i):
        x1, y1 = p[i]
        x2 , y2 = p[j]
        if (x1-x2)**2 + (y1-y2)**2 == 1:
            ans += 1
print(ans)

C. 小红的整数三角形

考虑构造直角三角形。

为了使得面积是整数,可以让另一条边扩大一倍。

时间复杂度

x1, y1, x2 , y2 = map(int, input().split())
x = x2 + 2 * y2 - 2 * y1
y = y2 + 2 * x1 - 2 * x2
print(x, y)

D.小红的马

不防考虑每个兵可以被哪些位置的马攻击。

可以发现点图和马可以攻击的点图是一样的。

那么就可以统计所有兵周围的 个点,再找最大的点即可。

时间复杂度

from collections import defaultdict
n = int(input())
memo = defaultdict(int)
vv = set()
for _ in range(n):
    x, y=  map(int, input().split())
    vv.add((x, y))
for x, y in vv:
    for dx, dy in [(-1, -2), (1, 2), (1, -2), (-1, 2)]:
        
        if (x+dx, y + dy) not in vv and x + dx > 0 and y + dy > 0:
            memo[(x+dx, y+dy)]+=1
        if (x + dy, y + dx) not in vv and x + dy > 0 and y + dx > 0:
            memo[(x+dy, y+dx)] += 1
mx = max(memo.values())
for k in memo:
    if memo[k] == mx:
        print(*k)
        break

E.小红的好矩形

不难发现,我们可以考虑相邻的

具体的,对每个 的点 ,检查和 的点 相同的点。

如果有 个,则对答案的贡献为

同理。但注意长和宽均为 的矩形会被统计两次,要注意去重。

时间复杂度

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll>PLL;
#define fi first
#define se second
#define pb push_back
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    ll n;cin>>n;
    vector<PLL> p(n);
    for(ll i=0;i<n;i++) cin >> p[i].fi >> p[i].se;
    map<ll, map<ll, ll>> xs, ys;
    for(auto [x, y]:p){
        xs[x][y] = 1;
        ys[y][x] = 1;
    }
    ll ans = 0;
    for(auto [k, v]:xs){
        ll cnt = 0;
        for(auto [vv, _]:v){
            if(xs.contains(k+1)&&xs[k+1].contains(vv)){
                cnt++;
            }
        }
        ans += (cnt-1)*cnt/2;
    }
    for(auto [k, v]:ys){
        vector<ll> memo;
        for(auto [vv, _]:v){
            if(ys.contains(k+1)&&ys[k+1].contains(vv)){
                memo.pb(vv);
            }
        }
        ll t = memo.size();
        ll tt = t * (t-1)/2;
        for(ll i=1;i<memo.size();i++){
            if (memo[i]-memo[i-1]==1){
                tt--;
            }
        }
        ans += tt;
    }
    cout<<ans<<'\n';
}

F.小红的线下查询

注意到要求可以转化为:

所以可以转化为二维数点问题离线处理。

对所有点按 升序排序,对所有查询按 升序排序。

对每个查询,先把 的所有点的 加入树状数组中,在查询小于 的点有几个。

数据范围大,需要先离散化。

时间复杂度

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll>PLL;
#define fi first
#define se second
#define pb push_back
#define all(x) x.begin(), x.end()
class BIT{
    public:
    vector<ll> c;
    ll n;
    BIT(ll n_){
        n = n_;
        c.resize(n+1);
    }
    void add(ll x, ll d){
        for(;x<=n;x+=(x&-x)) c[x] += d;
    }
    ll query(ll x){
        if(x <= 0) return 0;
        ll res = 0;
        for(;x;x-=(x&-x)) res += c[x];
        return res;
    }
};
    
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    ll n, q;cin>>n>>q;
    vector<array<ll,4>> tot;
    vector<ll> pp;
    for(ll i=0;i<n;i++){
        ll x, y;cin>>x>>y;
        tot.pb({y-x, y+x, 0, i});
        pp.pb({y-x});
        pp.pb({y+x});
    }
    for(ll i=0;i<q;i++){
        ll k1, k2;cin>>k1>>k2;
        tot.pb({k1, k2, 1, i});
        pp.pb(k1);
        pp.pb(k2);
    }
    vector<ll> ans(q);
    sort(all(tot), [&](array<ll, 4> &x, array<ll, 4> & y){
        if(x[0]!=y[0]){
           return x[0]<y[0];
        }
        
        if(x[2]!=y[2]){
            return x[2]>y[2];
        }
        return x[1]<y[1];
    });
    map<ll, ll> name, back;
    ll idx = 1;
    sort(all(pp));
    for(auto v:pp){
        if(!name[v]){
            name[v] = idx;
            back[idx] = v;
            idx++;
        }
    }   
    BIT bit((ll)4e5+7);
    ll res = 0;
    for(auto [x, y, t, idx]:tot){
        if(t == 1){
            ans[idx] = bit.query(name[y]-1);
        }
        else{
            bit.add(name[y], 1);
        }
    }
    for(auto v:ans){
        cout<<v<<'\n';
    }
        
}