2013 Multi-University Training Contest 10
HDU-4698 Counting
题意:给定一个二维平面,其中x取值为1-N,y取值为1-M,现给定K个点,问至少包括K个点中的一个的满足要求的<Xmin, Xmax, Ymin, Ymax>共有多少中取值情况。也就是说K个点中至少一个点落在所给定的区间内。
解法:正面求解,由于点只有1000个,因此直接暴力离散化之后的x轴坐标,对于y轴则可以通过增加一个一个加入点,使用一个set来维护纵轴有多少种不同的取法。
#include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #include <set> using namespace std; typedef long long LL; const int N = 1005; const int mod = int(1e9)+7; const int inf = 0x7fffffff; struct Point { int x, y; Point() {} Point(int _x, int _y) : x(_x), y(_y) {} bool operator < (const Point &t) const { if (x != t.x) return x < t.x; else return y < t.y; } }p[N]; int n, m, K; int val[N]; set<int>st; set<int>::iterator it1, it2; int main() { while (scanf("%d %d %d", &n, &m, &K) != EOF) { for (int i = 1; i <= K; ++i) { scanf("%d %d", &p[i].x, &p[i].y); val[i] = p[i].x; } sort(p+1, p+K+1); sort(val+1, val+1+K); int cnt = unique(val, val+K+1)-val; // 去重之后的x轴坐标 val[0] = 0; val[cnt++] = n+1; LL ret = 0; for (int i = 1; i < cnt-1; ++i) { st.clear(); st.insert(0); st.insert(m+1); LL sum = 0; for (int j = i; j < cnt-1; ++j) { int left = lower_bound(p+1, p+1+K, Point(val[j], 0))-p; int right = upper_bound(p+1, p+1+K, Point(val[j], inf))-p; for (int k = left; k < right; ++k) { // x轴取值为val[j]的点一次性取出来 if (st.count(p[k].y)) continue; st.insert(p[k].y); it1 = it2 = st.find(p[k].y); it1--, it2++; // 找前一个和后一个 sum = (sum+1LL*(p[k].y-*(it1))*(*(it2)-p[k].y)%mod)%mod; // 新增加的y值对,统计只跨过该点的 } ret = (ret+sum*(val[i]-val[i-1])%mod*(val[j+1]-val[j])%mod)%mod } } printf("%I64d\n", ret); } return 0; }