hdu 4698 - Counting(思路)

来源:互联网 发布:三国群英战辅助软件 编辑:程序博客网 时间:2024/06/04 19:30

转:题意:给定一个二维平面,其中x取值为1-N,y取值为1-M,现给定K个点,问至少包括K个点中的一个的满足要求的<Xmin, Xmax, Ymin, Ymax>共有多少中取值情况。也就是说K个点中至少一个点落在所给定的区间内。

解法:正面求解,由于点只有1000个,因此直接暴力离散化之后的x轴坐标,对于y轴则可以通过增加一个一个加入点,使用一个set来维护纵轴有多少种不同的取法。

代码如下;

#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <set>#define LL long long#define mod 1000000007#define M 1005#define INF 0x7fffffffusing namespace std;struct Point{    int x, y;    bool operator < (const Point &temp) const    {        if(x!=temp.x) return x<temp.x;        else return y<temp.y;    }    int readPoint()    {        return scanf("%d%d", &x, &y);    }} p[M];int n, m, k;int val[M];set<int>sset;set<int>::iterator it;int main (){    while(~scanf("%d%d%d", &n, &m, &k))    {        for(int i = 1; i <= k; ++i)        {            p[i].readPoint();            val[i] = p[i].x;        }        sort(p+1, p+1+k);        sort(val+1, val+1+k);        int tot = unique(val+1, val+1+k) - val;        val[0] = 0;        val[tot] = n+1;        LL ans = 0;        for(int i = 1; i < tot; ++i)        {            LL tt = 0;            int pre = val[i]-val[i-1];            int r;            for(r = 1; r <= k && p[r].x < val[i]; ++r);            sset.clear();            sset.insert(0);            sset.insert(m+1);            for(int j = i; j < tot; ++j)            {                int top, bottom;                for( ; r <= k && p[r].x == val[j]; ++r)                {                    if(sset.count(p[r].y)) continue;                    it = sset.lower_bound(p[r].y);                    top = *it;                    bottom = *(--it);                    tt = (tt+(LL)(top-p[r].y)*(p[r].y-bottom)%mod)%mod;                    sset.insert(p[r].y);                }                int rear = val[j+1]-val[j];                ans = (ans+tt*rear%mod*pre%mod)%mod;            }        }        printf("%I64d\n", ans);    }    return 0;}


原创粉丝点击