CodeForces 1000F One Occurrence (线段树+离线/主席树)*

博客围绕一个序列查询问题展开,题目要求在给定序列和若干查询中,找出区间里只出现一次的数字。分析采用贪心思想,通过判断区间pre最小值与左端点的关系确定答案。介绍了线段树离线和主席树两种解法,时间复杂度为O(n+qlogn)。

题目链接:http://codeforces.com/problemset/problem/1000/F

题目大意

给定一个序列和若干个查询,
每次查询区间中只出现一次的那个数字,
若答案有若干个则输出任意一个,
否则输出零。

题目分析 

根据贪心的思想,对于一个特定的区间,
假设每个位置都有一个pre,即上一次出现该位置数的位置,
如果第一次出现明显位置应该为0,
一个区间中是否存在答案,就是看这个区间的pre最小值,是否
大于左端点,那么我们只要看其区间最小值即可,注意要存个二元组,,因为
如果pre值为0则无法确定位置数,一种常规方法是线段树离线,
因为在线的话不确定查询区间出现的时间顺序,
那么当前维护的线段树不会对以前的区间产生贡献,
离线可以解决这个问题,按右端点排序,直接往线段树按序更新值即可,
那么既然涉及到时间顺序的影响问题,主席树也是一个手段。
主席树就是暴力空间般把时间序都存储下来了,
但是一个时间刻只影响一条链所有空间不会特别大,
既然我们对每个扫描时间(总共n)都开线段树存储时间刻了,
那么对于这个时间线段树,当前位置的pre影响应该消去,
所以空间要开四倍左右,然后更新i位置用位置上的pre值即可。
最后直接在第r个树上区间查询找最小的即可。
时间复杂度:O(n+qlogn).

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

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e5+5;
const int maxm=2e7+5;
const int ub=1e6;
const int INF=1e9;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定一个序列和若干个查询,
每次查询区间中只出现一次的那个数字,
若答案有若干个则输出任意一个,
否则输出零。

题目分析:
根据贪心的思想,对于一个特定的区间,
假设每个位置都有一个pre,即上一次出现该位置数的位置,
如果第一次出现明显位置应该为0,
一个区间中是否存在答案,就是看这个区间的pre最小值,是否
大于左端点,那么我们只要看其区间最小值即可,注意要存个二元组,,因为
如果pre值为0则无法确定位置数,一种常规方法是线段树离线,
因为在线的话不确定查询区间出现的时间顺序,
那么当前维护的线段树不会对以前的区间产生贡献,
离线可以解决这个问题,按右端点排序,直接往线段树按序更新值即可,
那么既然涉及到时间顺序的影响问题,主席树也是一个手段。
主席树就是暴力空间般把时间序都存储下来了,
但是一个时间刻只影响一条链所有空间不会特别大,
既然我们对每个扫描时间(总共n)都开线段树存储时间刻了,
那么对于这个时间线段树,当前位置的pre影响应该消去,
所以空间要开四倍左右,然后更新i位置用位置上的pre值即可。
最后直接在第r个树上区间查询找最小的即可。
时间复杂度:O(n+qlogn).
*/
int rt[maxn],ls[maxm],rs[maxm];
struct node{ int pos , val; };
node sum[maxm];
int tot=0;
void build(int& o,int l,int r){
    o=++tot;
    sum[o].val=INF;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls[o],l,mid);
    build(rs[o],mid+1,r);
}
void update(int& o,int l,int r,int last,int p,int v){
    o=++tot;
    ls[o]=ls[last],rs[o]=rs[last];
    if(l==r){
        sum[o].val=v;
        sum[o].pos=l;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid) update(ls[o],l,mid,ls[o],p,v);
    else update(rs[o],mid+1,r,rs[o],p,v);
    if(sum[ls[o]].val<sum[rs[o]].val) sum[o]=sum[ls[o]];
    else sum[o]=sum[rs[o]];
}
node query(int o,int l,int r,int pl,int pr){
    if(pl<=l&&r<=pr) return sum[o];
    if(sum[o].val==INF) return sum[o];
    int mid=l+r>>1;
    node tp1,tp2;
    tp2.val=INF;
    if(pl<=mid){
        tp1=query(ls[o],l,mid,pl,pr);
        if(tp1.val<tp2.val) tp2=tp1;
    }
    if(mid<pr){
        tp1=query(rs[o],mid+1,r,pl,pr);
        if(tp1.val<tp2.val) tp2=tp1;
    }
    return tp2;
}
int a[maxn],n,x,y,q;
int pre[maxn],last[maxn];
int main(){
    scanf("%d",&n);
    build(rt[0],1,n);
    rep(i,1,n+1) scanf("%d",&a[i]);
    rep(i,1,n+1){
        if(last[a[i]]) pre[i]=last[a[i]];
        last[a[i]]=i;
    }
    rep(i,1,n+1){
        if(pre[i]){
            int tmp;
            update(tmp,1,n,rt[i-1],pre[i],INF);
            update(rt[i],1,n,tmp,i,pre[i]);
        }
        else update(rt[i],1,n,rt[i-1],i,0);
    }
    scanf("%d",&q);
    rep(i,0,q){
        scanf("%d%d",&x,&y);
        node ret=query(rt[y],1,n,x,y);
        if(ret.val>=x) puts("0");
        else printf("%d\n",a[ret.pos]);
    }

    return 0;
}

 

#include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <limits.h> #define eps 1e-9 //unsigned int F[14000010]; //unsigned long long arr[7500005]; //double arr1[1000000]; //double arr2[1000000]; //double Arr[1000000]; //int arr[1000010] = { 0 }; //int arrn[10010] = { 0 }; //int arr[100][100]; //E3H! //int is_ry(int y) //{ // int result; // result = (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); // return result; //} //int D(int y, int m) //{ // int D[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; // int ds = D[m]; // if (m == 2 && is_ry(y)) // { // D[2] = 29; // return 29; // } // return ds; //} //E3M int Max(int a, int b) { int result; if (a >= b) { result = a; } else { result = b; } return result; } int Min(int a, int b) { int result; if (a <= b) { result = a; } else { result = b; } return result; } int main() { //C3A //long long T; //scanf("%lld", &T); //unsigned int a, b; //for (int i = 0; i < T; i++) //{ // scanf("%u %u", &a, &b); // unsigned int n1 = ~a; // unsigned int n2 = a & b; // unsigned int n3 = a | b; // unsigned int n4 = a ^ b; // unsigned int n5 = a << b; // unsigned int n6 = a >> b; // printf("%u %u %u %u %u %u\n", n1, n2, n3, n4, n5, n6); //} //return 0; //C3B //long long n; //scanf_s("%lld", &n); //printf("0 "); //for (int k = 1; k <= n; k++) //{ // int sum = 0; // int arr[101]; // int f = floor(log2(k)); // int K = k; // for (int i = 0; i <= f; i++) // { // int N = K & 1; // arr[i] = N; // K = K >> 1; // } // for (int j = 0; j <= f; j++) // { // if (arr[j] == 1) // { // sum++; // } // } // printf("%d ", sum); //} //return 0; //C3C //int nn; //scanf_s("%d", &nn); //int n; //for (int i = 0; i < nn; i++) //{ // int arr[101] = {0}; // unsigned long long n; // scanf_s("%llu", &n); // unsigned long long f = floor(log2(n)); // unsigned long long N = n; // for (int i = 0; i <= f; i++) // { // unsigned long long N = n & 1; // arr[i] = N; // n = n >> 1; // } // for (int j = 63; j >= 0; j=j-4) // { // printf("%d%d%d%d ", arr[j],arr[j-1],arr[j-2],arr[j-3]); // } // printf("\n"); //} //return 0; //C3D //int n; //unsigned int sum=0; //scanf_s("%d", &n); //for (int i = 0; i < n; i++) //{ // sum = 0; // int arr[101] = {0}; // unsigned int n; // scanf_s("%u", &n); // int f = floor(log2(n)); // unsigned int N = n; // for (int i = 0; i <= f; i++) // { // unsigned int N = n & 1; // arr[i] = N; // n = n >> 1; // } // for (int j = 0; j <= 32; j++) // { // sum = sum + pow(2, j) * arr[31-j]; // } // printf("%u\n", sum); //} //C3E //int nn; //scanf_s("%d", &nn); //for (int i = 0; i < nn; i++) //{ // int arr[101]; // int n; // scanf_s("%d", &n); // int f = floor(log2(n)); // int N = n; // for (int i = 0; i <= f; i++) // { // int N = n & 1; // arr[i] = N; // n = n >> 1; // } // int k = 0; // int Arr[101]; // for (int j = f; j >= 0; j--) // { // if (arr[j] == 1) // { // Arr[k] = j; // k++; // } // } // for (int t = 0; t < k; t++) // { // printf("%.0lf ", pow(2, Arr[t])); // } // printf("\n"); //} //return 0; //C3F //int n, q; //scanf_s("%d%u%d", &n, &F[0], &q); //int k; //for (int i = 1; i <= n; i++) //{ // unsigned int x = F[i - 1]; // x ^= x << 13; // x ^= x >> 17; // x ^= x << 5; // F[i] = x; //} //while (q--) //{ // scanf_s("%d", &k); // printf("%u\n", F[k]); //} //return 0; //C3G //int n; //int a; //int b=0; //scanf_s("%d", &n); //for (int i = 0; i < n; i++) //{ // scanf_s("%d", &a); // b = b ^ a; //} //printf("%d\n", b); //return 0; //E3A //int a, b, c, x; //scanf_s("%d%d%d%d", &a, &b, &c, &x); //int A = a * x * x + b * x + c; //printf("%d", A); //return 0; //E3B //int n; //scanf_s("%d", &n); //int i = n; //for (int i = n; i > 1; i--) //{ // printf("%d bottles of beer on the wall,\n", i); // printf("%d bottles of beer.\n", i); // printf("Take one down and pass it around,\n"); // if (i == 2) // { // printf("now there's %d more bottle of beer on the wall!\n", i-1); // } // else // printf("now there's %d more bottles of beer on the wall!\n", i - 1); //} // printf("1 bottle of beer on the wall,\n"); // printf("1 bottle of beer.\n"); // printf("Take one down and pass it around,\n"); // printf("there's no more bottles of beer on the wall!\n"); //return 0; //E3C //unsigned long long a, b; //while (scanf_s("%llu%llu", &a, &b) != EOF) //{ // unsigned long long i = 0; // unsigned long long t = 0; // for (i = 0; i < 64; i++) // { // unsigned long long ai = a >> i; // unsigned long long bi = b >> i; // unsigned long long Ai = ai & 1; // unsigned long long Bi = bi & 1; // if (Ai - Bi == 1) // { // t = t | (1ULL << i); // } // } // printf("%llu\n", t); //} //return 0; //E3D //int T, n; //scanf_s("%d", &T); //arr[1] = 1; //unsigned long long temp=1; //for (int j = 2; j <= 7.5e6; j++) //{ // temp = (temp * j) % 998244353; // arr[j] = temp; //} //for (int i = 1; i <= T; i++) //{ // scanf_s("%d", &n); // printf("%llu\n", arr[n]); //} //return 0; //E3E //int T; //scanf_s("%d", &T); //double sum1 = 0.000000; //double sum2 = 0.000000; //double sign = 1.0; //for (int i = 1; i <= 100000; i++) //{ // sum1 = sum1 + sign *1.000000/ (2 * i - 1); // sign = -sign; // arr1[i] = sum1; //} //for (int i = 1; i <= 100000; i++) //{ // sum2 = sum2 + 1.000000 / (long long)((long long)(2 * i - 1) * (long long)(2 * i - 1)); // arr2[i] = sum2; //} //for (int i = 1; i <= 100000; i++) //{ // Arr[i] = arr1[i] * 4 - sqrt(8 * arr2[i]); //} //int arrn[1000]; //int arrN[1000]; //for (int j = 1; j <= T; j++) //{ // scanf_s("%d", &arrn[j]); // arrN[j] = arrn[j]; //} //for (int k = 1; k <= T; k++) //{ // printf("%.6lf\n", fabs(Arr[arrN[k]])); //} //return 0; //E3F? //int n; //int a; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d", &a); // arrn[i] = a; //} //for (int j = 1; j <= 10000; j++) //{ // for (int k = 1; k <= 1000000; k++) // { // if (j == arrn[k]) // { // arr[j]++; // } // } // if (arr[j] != 0) // { // printf("%d : %d\n", j, arr[j]); // } //} //return 0; //E3F //int n; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d",&arr[i]); // arrn[arr[i]]++; //} //for (int i = 1; i <= 10000; i++) //{ // if (arrn[i] > 0) // { // printf("%d : %d\n", i, arrn[i]); // } //} //E3G? //int m, n; //int x0, y0; //int x, y; //scanf_s("%d%d", &n, &m); //scanf_s("%d%d", &x0, &y0); //scanf_s("%d%d", &x, &y); //for (int xi = 1; xi <= n; xi++) //{ // for (int yi = 1; yi <= m; yi++) // { // printf("0"); // } // printf("0\n"); //} //E3G! //long long n, m; //long long x0, y0; //long long x, y; //scanf_s("%lld%lld", &n,& m); //scanf_s("%lld%lld", &x0, &y0); //scanf_s("%lld%lld", &x, &y); //for (long long i = x - 2; i <= x + 2; i++) //{ // for (long long j = y - 2; j <= y + 2; j++) // { // if (i == x0 && j == y0) // { // printf("+"); // } // else if (i == x0 && j != y0) // { // printf("-"); // } // else if (i != x0 && j == y0) // { // printf("|"); // } // else if (i - x0 == j - y0) // { // printf("\\"); // } // else if (i - x0 == y0 - j) // { // printf("/"); // } // else if (i - x0 < 0 && j - y0>0 && x0 - i > j - y0) // { // printf("A"); // } // else if (i < x0 && j > y0 && x0 - i < j - y0) // { // printf("B"); // } // else if (i > x0 && j > y0 && i - x0 < j - y0) // { // printf("C"); // } // else if (i > x0 && j > y0 && i - x0 > j - y0) // { // printf("D"); // } // else if (i > x0 && j < y0 && i - x0 > y0 - j) // { // printf("E"); // } // else if (i > x0 && j < y0 && i - x0 < y0 - j) // { // printf("F"); // } // else if (i < x0 && j < y0 && i - x0 < j - y0) // { // printf("H"); // } // else // { // printf("G"); // } // } // printf("\n"); //} //return 0; //E3H? //int n; //scanf_s("%d", &n); //int y, m, d, h, mi; //for (int i = 1; i <= n; i++) //{ // scanf_s("%d.%d.%d %d:%d", &y, &m, &d, &h, &mi); //} //E3H! //int n; //scanf_s("%d", &n); //while (n--) //{ // int y, m, d, h, mi; // scanf_s("%d.%d.%d %d:%d", &y, &m, &d, &h, &mi); // while (mi >= 60) // { // mi = mi - 60; // h++; // } // while (h >= 24) // { // h = h - 24; // d++; // } // while (1) // { // while (m > 12) // { // m = m - 12; // y++; // } // int DD = D(y, m); // if (d <= DD) // { // break; // } // d = d - DD; // m++; // } // if (y >= 10000) // { // printf("%05d.%02d.%02d %02d:%02d\n", y, m, d, h, mi); // } // else // { // printf("%04d.%02d.%02d %02d:%02d\n", y, m, d, h, mi); // } //} //return 0; //E3I? //long long a, b, n; //scanf_s("%lld%lld%lld", &a, &b, &n); //long long ZHENG = a / b; //long long XIAO = a % b; //long long arr[110] = {0}; //for (int i = 1; i <= n + 1; i++) //{ // XIAO = XIAO * 10; // long long A = XIAO / b; // XIAO = XIAO % b; // arr[i] = A; //} //if (arr[n + 1] >= 5) //{ // arr[n]++; // for (int i = n; i >= 2; i--) // { // if (arr[i] >= 10) // { // arr[i] = arr[i] - 10; // arr[i - 1]++; // } // } // if (arr[1] >= 10) // { // arr[1] = arr[1] - 10; // ZHENG++; // } //} //printf("%lld.", ZHENG); //for (int i = 1; i <= n; i++) //{ // printf("%lld", arr[i]); //} //printf("\n"); //return 0; //E3K //int a, b; //scanf_s("%d%d", &a, &b); //double down= floor(a * 1.000000 / b); //double up = ceil(a * 1.000000 / b); //if (down == 0.0) //{ // down = 0.0; //} //if (up == 0.0) //{ // up = 0.0; //} //printf("%.lf %.lf", down, up); //return 0; //E3L? //int T; //int a; //scanf_s("%d", &T); //for (int i = 1; i <= T; i++) //{ // scanf_s("%d", &a); // if (a % 6 == 0) // { // printf("Tom wins\n"); // } // else // { // printf("Jerry wins\n"); // } //} //return 0; //E3M int T; scanf_s("%d", &T); int a1, b1, c1, d1, a2, b2, c2, d2; for (int i = 1; i <= T; i++) { scanf_s("%d%d%d%d%d%d%d%d", &a1, &b1, &c1, &d1, &a2, &b2, &c2, &d2); float X1 = (a1 + c1) * 1.0f / 2; float X2 = (a2 + c2) * 1.0f / 2; float Y1 = (d1 + b1) * 1.0f / 2; float Y2 = (d2 + b2) * 1.0f / 2; float rx1 = fabs(a1 - c1) * 1.0f / 2; float rx2 = fabs(a2 - c2) * 1.0f / 2; float ry1 = fabs(d1 - b1) * 1.0f / 2; float ry2 = fabs(d2 - b2) * 1.0f / 2; float dX = fabs(X1 - X2)*1.0f; float dY = fabs(Y1 - Y2)*1.0f; float S1 = 4 * rx1 * ry1*1.0f; float S2 = 4 * rx2 * ry2*1.0f; float SS = S1 + S2; float TT = fabs(Max(a1, a2) - Min(c1, c2)) * fabs(Min(d1, d2) - Max(b1, b2)); float dst = SS - TT; if (TT < 0.0f) { TT = 0.0f; } if (SS - TT < 0.0f) { dst= 0.0f; } if (dX < rx1 + rx2 && dY < ry1 + ry2) { printf("%d %d\n", (int)round(TT), (int)round(dst)); } else { printf("%d %d\n", 0, (int)round(dst)); } } return 0; //E3Y //int n; //int arr[22]; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d", &arr[i]); //} //int max = 0; //int Max = 0; //int min = 100; //int Min = 0; //for (int i = 1; i <= n; i++) //{ // if (arr[i] > max) // { // max = arr[i]; // Max = i; // } // if (arr[i] < min) // { // min = arr[i]; // Min = i; // } //} //arr[Min] = 0; //arr[Max] = 0; //double sum = 0.0; //double ave = 0.0; //for (int i = 1; i <= n; i++) //{ // sum = sum + arr[i]; //} //ave= sum / (n - 2); //int cut = ave * 100; //double decut = cut * 1.00 / 100; //printf("%.2lf", decut); //return 0; }WA为什么
最新发布
10-02
你提供的代码是一个包含多个被注释掉的测试用例(如 `C3A`, `C3B`, ..., `E3Y`)的 C 程序,最终只启用了 `E3M` 部分。你说“WA”(Wrong Answer),说明这个程序在某个在线判题系统(比如 OJ、洛谷、Codeforces、牛客等)上提交后没有通过。 我们来**逐行分析你当前启用的代码段 E3M**,找出可能导致 **WA 的原因**。 --- ### ✅ 当前运行的代码:`E3M` ```c int main() { int T; scanf_s("%d", &T); int a1, b1, c1, d1, a2, b2, c2, d2; for (int i = 1; i <= T; i++) { scanf_s("%d%d%d%d%d%d%d%d", &a1, &b1, &c1, &d1, &a2, &b2, &c2, &d2); float X1 = (a1 + c1) * 1.0f / 2; float X2 = (a2 + c2) * 1.0f / 2; float Y1 = (d1 + b1) * 1.0f / 2; float Y2 = (d2 + b2) * 1.0f / 2; float rx1 = fabs(a1 - c1) * 1.0f / 2; float rx2 = fabs(a2 - c2) * 1.0f / 2; float ry1 = fabs(d1 - b1) * 1.0f / 2; float ry2 = fabs(d2 - b2) * 1.0f / 2; float dX = fabs(X1 - X2)*1.0f; float dY = fabs(Y1 - Y2)*1.0f; float S1 = 4 * rx1 * ry1*1.0f; float S2 = 4 * rx2 * ry2*1.0f; float SS = S1 + S2; float TT = fabs(Max(a1, a2) - Min(c1, c2)) * fabs(Min(d1, d2) - Max(b1, b2)); float dst = SS - TT; if (TT < 0.0f) { TT = 0.0f; } if (SS - TT < 0.0f) { dst= 0.0f; } if (dX < rx1 + rx2 && dY < ry1 + ry2) { printf("%d %d\n", (int)round(TT), (int)round(dst)); } else { printf("%d %d\n", 0, (int)round(dst)); } } return 0; } ``` --- ## ❌ 问题定位与 WA 原因分析 ### 🔍 题意推测(根据变量命名和逻辑) 这道题很可能是: > 给定两个矩形(由左下角和右上角坐标定义),求: > > 1. 两矩形的交集面积; > 2. 并集面积。 > > 输出格式为:`交集面积 并集面积` 但你的变量含义如下: - `S1`, `S2`: 两个矩形面积 - `SS`: 总面积(即 `S1 + S2`) - `TT`: 尝试计算交集面积 - `dst`: `SS - TT` → 实际是“总面积减去交集”,也就是并集?❌ 这里已经错了! ⚠️ 正确关系是: ``` 并集面积 = S1 + S2 - 交集面积 => 所以如果 TT 是交集,则 并集 = SS - TT ``` 那你把 `dst = SS - TT` 定义成“并集”是对的。 但是你在输出时却打印了: ```c printf("%d %d\n", (int)round(TT), (int)round(dst)); // 即:交集 和 并集? ``` 看起来像是输出:`交集 并集` 但注意:题目是否要求的是 **交集 和 并集**?还是别的? 更重要的是——你对交集面积 `TT` 的计算方式是错误的! --- ### 🛠 错误一:`TT` 计算方式错误 ```c float TT = fabs(Max(a1, a2) - Min(c1, c2)) * fabs(Min(d1, d2) - Max(b1, b2)); ``` 这是想计算交集矩形的宽 × 高。 但你搞反了!正确的交集宽度应该是: ```text overlap_width = min(c1, c2) - max(a1, a2) overlap_height = min(d1, d2) - max(b1, b2) ``` 然后: ```c if (overlap_width > 0 && overlap_height > 0) intersection = overlap_width * overlap_height; else intersection = 0; ``` 而你写成了: ```c fabs(Max(a1, a2) - Min(c1, c2)) ``` 这等于 `min(c1,c2) - max(a1,a2)` 只有当 `min(c1,c2) >= max(a1,a2)` 时才是正数,否则负数会被 `fabs` 强行转为正 → 导致错误! 👉 **使用 `fabs` 是致命错误!** 例如:矩形不相交时,`max(a1,a2) > min(c1,c2)` → 差值为负 → `fabs(...)` 变成正数 → 错误地认为有交集! ✅ 正确做法应是: ```c float x_overlap = Min(c1, c2) - Max(a1, a2); float y_overlap = Min(d1, d2) - Max(b1, b2); float TT = (x_overlap > 0 && y_overlap > 0) ? x_overlap * y_overlap : 0; ``` 而不是先取 `fabs`! --- ### 🛠 错误二:坐标理解可能出错 你输入的四个点 `(a1, b1), (c1, d1)` 是否一定是左下和右上? 题目中并未保证这一点。也就是说,用户可能输入任意两个对角点。 所以你应该自己规范化: ```c int rect1_left = Min(a1, c1); int rect1_right = Max(a1, c1); int rect1_bottom = Min(b1, d1); int rect1_top = Max(b1, d1); // 同理处理 rect2 ``` 否则直接拿 `a1, c1` 当左右边界会出错。 --- ### 🛠 错误三:浮点数不必要的使用 + round 浮动误差 你全用了 `float`,还用了 `round()`,但实际上所有输入都是整数,面积也应是整数。 建议全程使用 `int` 来避免精度问题。 而且最后强制 `(int)round(x)` 在接近整数时可能会因浮点误差导致进位错误。 --- ### 🛠 错误四:条件判断冗余且混乱 你写了: ```c if (dX < rx1 + rx2 && dY < ry1 + ry2) ``` 这似乎是用中心距离判断是否有交集,但其实没必要,因为可以直接通过重叠区域是否为正来判断。 你现在既用几何中心法判断是否相交,又手动算 `TT`,两者不一致,容易出错。 --- ## ✅ 正确解法(修复版) 以下是修复后的完整正确版本(假设每个矩形给的是任意两个对角顶点): ```c #include <stdio.h> int Max(int a, int b) { return a > b ? a; } int Min(int a, int b) { return a < b ? a; } int main() { int T; scanf("%d", &T); while (T--) { int a1, b1, c1, d1, a2, b2, c2, d2; scanf("%d%d%d%d%d%d%d%d", &a1, &b1, &c1, &d1, &a2, &b2, &c2, &d2); // 规范化矩形1 int x1_min = Min(a1, c1), x1_max = Max(a1, c1); int y1_min = Min(b1, d1), y1_max = Max(b1, d1); // 规范化矩形2 int x2_min = Min(a2, c2), x2_max = Max(a2, c2); int y2_min = Min(b2, d2), y2_max = Max(b2, d2); // 求交集 int inter_x_left = Max(x1_min, x2_min); int inter_x_right = Min(x1_max, x2_max); int inter_y_bottom = Max(y1_min, y2_min); int inter_y_top = Min(y1_max, y2_max); int inter_area = 0; int union_area = 0; if (inter_x_left < inter_x_right && inter_y_bottom < inter_y_top) { inter_area = (inter_x_right - inter_x_left) * (inter_y_top - inter_y_bottom); } int area1 = (x1_max - x1_min) * (y1_max - y1_min); int area2 = (x2_max - x2_min) * (y2_max - y2_min); union_area = area1 + area2 - inter_area; printf("%d %d\n", inter_area, union_area); } return 0; } ``` --- ## ✅ 对比原代码的主要修正点: | 问题 | 原代码错误 | 修复方法 | |------|-----------|--------| | 1. 坐标未标准化 | 直接用 `a1, c1` 当左右 | 使用 `Min/Max` 规范化 | | 2. 交集面积计算错误 | 用了 `fabs(Max - Min)` | 改为 `min(右) - max(左)`,负值则无交集 | | 3. 浮点运算引入误差 | 用 `float` 和 `round` | 全部改用整数运算 | | 4. 判断相交方式错误 | 中心距+半径判断 | 改为直接看交集区域是否有效 | --- ## ✅ 示例测试 输入: ``` 1 0 0 2 2 1 1 3 3 ``` 期望输出: ``` 1 7 ``` 解释: - 矩形1: (0,0)-(2,2),面积=4 - 矩形2: (1,1)-(3,3),面积=4 - 交集: (1,1)-(2,2),面积=1 - 并集: 4+4-1=7 你的原始代码很可能输出错误结果。 --- ## ✅ 为什么 WA? 总结一下导致 **WA** 的主要原因: 1. ❌ 使用 `fabs(Max(a1,a2) - Min(c1,c2))` 错误地计算交集宽度,即使不相交也会返回正值; 2. ❌ 未对输入坐标进行规范化(不能假设 `a1 < c1`); 3. ❌ 多余使用浮点数和 `round()`,引入精度问题; 4. ❌ 用中心距离判断交集,与面积计算逻辑冲突。 --- ## ✅ 推荐调试技巧 - 在本地加测试样例验证; - 使用标准库函数或手写小工具生成测试数据; - 提交前确保能 AC 样例。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值