1. 程式人生 > 實用技巧 >SQL注入之布林盲註腳本

SQL注入之布林盲註腳本

1. gym102465F

題意:給定$n$個有權值的平面點,求選兩點連線,使得直線兩邊權值和差最小

思路就是列舉每個點極角排序,滑動區間維護長π的區間的權值和

#include <bits/stdc++.h>
using namespace std;
const int N = 4e3+10;
const double pi = acos(-1);
struct point {
    int x,y,z;
} a[N];
pair<double,int> b[N*2];
int main() {
    int n;
    scanf("%d", &n);
    int64_t sum 
= 0; for (int i=1; i<=n; ++i) { scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z); sum += a[i].z; } int64_t ans = sum; for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) if (i!=j) { b[j-(i<j)] = {atan2(a[j].y-a[i].y,a[j].x-a[i].x),a[j].z}; } sort(b
+1,b+n); for (int j=1; j<n; ++j) b[j+n-1] = {b[j].first+2*pi,b[j].second}; int now = 1; int64_t w = 0; for (int j=1; j<n; ++j) { while (now<=2*n-2&&b[now].first-b[j].first<pi) w += b[now++].second; ans = min(ans, abs((w-b[j].second)-(sum-a[i].z-w))); w
-= b[j].second; } } printf("%lld\n", ans); }
按tan2排序
#include <bits/stdc++.h>
using namespace std;
const int N = 4e3+10;
const double pi = acos(-1);
struct point {
    int x,y,z,tp;
    bool operator < (const point & b) const {
        if (tp!=b.tp) return tp<b.tp;
        return y*(int64_t)b.x<x*(int64_t)b.y;
    }
} a[N],b[N*2];
int get(int x, int y) {
    if (x>0&&y>=0) return 1;
    if (x<=0&&y>0) return 2;
    if (x<0&&y<=0) return 3;
    return 4;
}
int main() {
    int n;
    scanf("%d", &n);
    int64_t sum = 0;
    for (int i=1; i<=n; ++i) { 
        scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
        sum += a[i].z;
    }
    int64_t ans = sum;
    for (int i=1; i<=n; ++i) {
        int tot = 0;
        for (int j=1; j<=n; ++j) if (i!=j) { 
            ++tot;
            b[tot] = {a[j].x-a[i].x,a[j].y-a[i].y,a[j].z};
            b[tot].tp = get(b[tot].x,b[tot].y);
        }
        sort(b+1,b+tot+1);
        for (int j=1; j<n; ++j) ++tot, b[tot] = b[j], b[tot].tp += 4;
        int now = 1;
        int64_t w = 0;
        for (int j=1; j<n; ++j) {
            point u{-b[j].x,-b[j].y,b[j].z,b[j].tp+2};
            while (now<=tot&&b[now]<u) w += b[now++].z;
            ans = min(ans, abs((w-b[j].z)-(sum-a[i].z-w)));
            w -= b[j].z;
        }
    }
    printf("%lld\n", ans);
}
按叉積排序

2. gym102361A

題意:給定$n$個點$P_i$,$q$個詢問,給定點$A_i$,求多少二元組$(u,v)$,滿足$A_i,P_u,P_v$為直角三角形

按每個詢問點極角排序,可以求出詢問點為直角頂點的答案。然後離線按每個給定點極角排序,求出每個詢問點為銳角頂點的答案

#include <bits/stdc++.h>
using namespace std;
const int N = 4e3+10;
struct point {
    int x,y,tp;
    bool operator < (const point & b) const {
        if (tp!=b.tp) return tp<b.tp;
        return y*(int64_t)b.x<x*(int64_t)b.y;
    }
    bool operator <= (const point &b) const {
        return !(b<*this);
    }
} a[N],b[N],f[N*2];
pair<point,int> g[N];
int ans[N];
int get(int x, int y) {
    if (x>0&&y>=0) return 1;
    if (x<=0&&y>0) return 2;
    if (x<0&&y<=0) return 3;
    return 4;
}
int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i=1; i<=n; ++i) scanf("%d%d", &a[i].x, &a[i].y);
    for (int i=1; i<=q; ++i) { 
        scanf("%d%d", &b[i].x, &b[i].y);
        for (int j=1; j<=n; ++j) {
            f[j] = {a[j].x-b[i].x,a[j].y-b[i].y};
            f[j].tp = get(f[j].x,f[j].y);
        }
        sort(f+1,f+1+n);
        for (int j=1; j<=n; ++j) f[j+n] = f[j], f[j+n].tp += 4;
        int lx = 1, rx = 1;
        for (int j=1; j<=n; ++j) {
            point u{-f[j].y,f[j].x,f[j].tp+1};
            while (lx<=2*n&&f[lx]<u) ++lx;
            while (rx<=2*n&&f[rx]<=u) ++rx;
            ans[i] += rx-lx;
        }
    }
    for (int i=1; i<=n; ++i) {
        int tot = 0;
        for (int j=1; j<=n; ++j) if (i!=j) {
            f[++tot] = {a[j].x-a[i].x,a[j].y-a[i].y};
            f[tot].tp = get(f[tot].x,f[tot].y);
        }
        sort(f+1,f+1+tot);
        for (int j=1; j<n; ++j) ++tot, f[tot] = f[j], f[tot].tp += 4;
        for (int j=1; j<=q; ++j) { 
            g[j].first = {b[j].x-a[i].x,b[j].y-a[i].y};
            g[j].first.tp = get(g[j].first.x,g[j].first.y);
            g[j].second = j;
        }
        sort(g+1,g+1+q);
        int lx = 1, rx = 1;
        for (int j=1; j<=q; ++j) {
            point v{-g[j].first.y,g[j].first.x,g[j].first.tp+1};
            while (lx<=tot&&f[lx]<v) ++lx;
            while (rx<=tot&&f[rx]<=v) ++rx;
            ans[g[j].second] += rx-lx;
        }
        lx = rx = tot;
        for (int j=q; j; --j) {
            point v{g[j].first.y,-g[j].first.x,g[j].first.tp-1+4};
            while (lx>=1&&v<f[lx]) --lx;
            while (rx>=1&&v<=f[rx]) --rx;
            ans[g[j].second] += lx-rx;
        }
    }
    for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
}
View Code

因為只用求直角,可以不極角排序,直接把向量reduce後判斷

#include <bits/stdc++.h>
using namespace std;
const int N = 2e3+10;
int n, q;
struct point {
    int x, y;
} a[N], b[N];
pair<int,int> f[N];
int ans[N];
int gcd(int x, int y) {return y?gcd(y,x%y):x;}
pair<int,int> reduce(int x, int y) {
    int g = gcd(abs(x),abs(y));
    if (g) x /= g, y /= g;
    return pair<int,int>(x,y);
}
int main() {
    scanf("%d%d", &n, &q);
    for (int i=1; i<=n; ++i) scanf("%d%d", &a[i].x, &a[i].y);
    for (int i=1; i<=q; ++i) { 
        scanf("%d%d", &b[i].x, &b[i].y);
        for (int j=1; j<=n; ++j) f[j] = reduce(a[j].y-b[i].y,a[j].x-b[i].x);
        sort(f+1,f+1+n);
        for (int j=1; j<=n; ++j) {
            pair<int,int> u = reduce(-f[j].second,f[j].first);
            ans[i] += upper_bound(f+1,f+1+n,u)-lower_bound(f+1,f+1+n,u);
        }
    }
    for (int i=1; i<=n; ++i) {
        for (int j=1; j<=n; ++j) if (i!=j) f[j-(i<j)] = reduce(a[j].y-a[i].y,a[j].x-a[i].x);
        sort(f+1,f+n);
        for (int j=1; j<=q; ++j) {
            pair<int,int> u = reduce(-(b[j].x-a[i].x),b[j].y-a[i].y);
            ans[j] += upper_bound(f+1,f+n,u)-lower_bound(f+1,f+n,u);
            u.first = -u.first, u.second = -u.second;
            ans[j] += upper_bound(f+1,f+n,u)-lower_bound(f+1,f+n,u);
        }
    }
    for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
}
View Code