已知问题
1.第一次看题的时候以为可以给任意一人送任意个礼物,且礼物可以重复送,想不出解法。
2.没有注意到N*A[i]=10^14,那么必须开long long才能统计下来。
题解
题目要求对于A的每一个喜欢的礼物,对于B来说都有一些比这些礼物更好的礼物,但是这些B喜欢的礼物里,只能给B送A没有那么喜欢的。
设礼物的两个维度分别为a[i]和b[i](对a[i]从小到大排序),那么对于每一个a[i],显然对小A来说,这个礼物之前的礼物都"没有那么喜欢"。
那么,对于小B呢?小B也有一样的要求,问题是候选的礼物里只有小A同意了才能送给小B。换句话讲,小B只能从"小A没那么喜欢"的礼物堆里挑礼物。
而在这个礼物堆中,只能送那些b[j]>=b[i]的给小B。换句话讲,就转化成了动态求逆序对问题。
就用树状数组统计就行。(首先要离散化)
#include<cstdio> #include<iostream> #include<algorithm> #include<map> #define int long long using namespace std; const int MAXN = 4e5; struct Point { int x, y; bool operator <(const Point &another)const { if (x == another.x) { return y > another.y; } else return x < another.x; } }p[MAXN]; int vals[MAXN], cnt = 0; int c[MAXN]; int lowbit(int x) { return x & -x; } void add(int x, int k) { while (x <= cnt) { c[x] += k; x += lowbit(x); } } int sum(int l, int r) { l--; int ans = 0; while (r) { ans += c[r]; r -= lowbit(r); } while (l) { ans -= c[l]; l -= lowbit(l); } return ans; } signed main() { int n; scanf("%lld", &n); for (int i = 1; i <= n; i++) { scanf("%lld", &p[i].x); vals[++cnt] = p[i].x; } for (int i = 1; i <= n; i++) { scanf("%lld", &p[i].y); vals[++cnt] = p[i].y; } sort(vals + 1, vals + cnt + 1); cnt = unique(vals + 1, vals + cnt + 1) - (vals + 1); map<int, int> valMap; for (int i = 1; i <= cnt; i++) { valMap[vals[i]] = i; } for (int i = 1; i <= n; i++) { p[i].x = valMap[p[i].x]; p[i].y = valMap[p[i].y]; } sort(p + 1, p + n + 1);//用x sort //二维偏序 int ans = 0; int sameCnt = 0; for (int i = 1; i <= n; i++) { //printf("p[%d]:(%d,%d)\n", i, p[i].x, p[i].y); if (i < n && (p[i].x == p[i + 1].x&&p[i].y == p[i + 1].y)) { sameCnt++; } else { if (sameCnt > 0&&(p[i].x!=p[i+1].x||p[i].y!=p[i+1].y)) { sameCnt++; ans += sameCnt*(sameCnt - 1) / 2; sameCnt = 0; } } ans += sum(p[i].y, cnt); add(p[i].y, 1); //对于每个p[i].x,找y大于等于p[i].y的数量 } ans += n; cout << ans << endl; return 0; }