BZOJ 1227: [SDOI2009]虔诚的墓主人

1227: [SDOI2009]虔诚的墓主人

Time Limit: 5 Sec  Memory Limit: 259 MB
Submit: 1078  Solved: 510
[Submit][Status][Discuss]

Description

小W 是一片新造公墓的管理人。公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地。当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地。为了体现自己对主的真诚,他们希望自己的墓地拥有着较高的虔诚度。一块墓地的虔诚度是指以这块墓地为中心的十字架的数目。一个十字架可以看成中间是墓地,墓地的正上、正下、正左、正右都有恰好k 棵常青树。小W 希望知道他所管理的这片公墓中所有墓地的虔诚度总和是多少

Input

第一行包含两个用空格分隔的正整数N 和M,表示公墓的宽和长,因此这个矩形公墓共有(N+1) ×(M+1)个格点,左下角的坐标为(0, 0),右上角的坐标为(N, M)。第二行包含一个正整数W,表示公墓中常青树的个数。第三行起共W 行,每行包含两个用空格分隔的非负整数xi和yi,表示一棵常青树的坐标。输入保证没有两棵常青树拥有相同的坐标。最后一行包含一个正整数k,意义如题目所示。

Output

包含一个非负整数,表示这片公墓中所有墓地的虔诚度总和。为了方便起见,答案对2,147,483,648 取模。

Sample Input

5 6
13
0 2
0 3
1 2
1 3
2 0
2 1
2 4
2 5
2 6
3 2
3 3
4 3
5 2
2

Sample Output

6

HINT

 

图中,以墓地(2, 2)和(2, 3)为中心的十字架各有3个,即它们的虔诚度均为3。其他墓地的虔诚度为0。


所有数据满足1 ≤ N, M ≤ 1,000,000,000,0 ≤ xi ≤ N,0 ≤ yi ≤ M,1 ≤ W ≤ 100,000, 1 ≤ k ≤ 10。存在50%的数据,满足1 ≤ k ≤ 2。存在25%的数据,满足1 ≤ W ≤ 10000。


注意:”恰好有k颗树“,这里的恰好不是有且只有,而是从>=k的树中恰好选k棵

 

Source

 
[Submit][Status][Discuss]

 

 

和前几天的考试题一模一样,然而当时脑子短路没想到,相见恨晚啊……

 

首先离散化坐标,然后树状数组维护一维上区间方案数和,扫描线统计,巨机智。

 

 1 #include <bits/stdc++.h>
 2 typedef long long lnt;
 3 const int siz = 500005;
 4 const lnt mod = 2147483648LL;
 5 struct Pair {
 6     int x, y;
 7     inline friend bool operator <
 8     (const Pair &a, const Pair &b) {
 9         if (a.y == b.y)
10             return a.x < b.x;
11         else
12             return a.y < b.y;
13     }
14 }t[siz];
15 int n, m, map[siz], tot, X[siz], Y[siz], now[siz];
16 lnt tr[siz], c[siz][15], ans;
17 inline lnt ask(int p) {
18     lnt ret = 0;
19     for (; p; p -= p&-p)
20         (ret += tr[p]) %= mod;
21     return ret;
22 }
23 inline void add(int p, lnt v) {
24     if (v >= mod)v %= mod;
25     for (; p <= tot; p += p&-p)
26         (tr[p] += v) %= mod;
27 }
28 signed main(void) {
29     scanf("%*d%*d%d", &n);
30     for (int i = 0; i < n; ++i)
31         scanf("%d%d", &t[i].x, &t[i].y);
32     scanf("%d", &m);
33     for (int i = 0; i < n; ++i)
34         map[tot++] = t[i].x, map[tot++] = t[i].y;
35     std::sort(t, t + n);
36     std::sort(map, map + tot);
37     tot = std::unique(map, map + tot) - map;
38     for (int i = 0; i <= n; ++i) {
39         c[i][0] = c[i][i] = 1;
40         for (int j = 1; j < i && j <= m; ++j)
41             c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
42     }
43     for (int i = 0; i < n; ++i)
44         ++X[std::lower_bound(map, map + tot, t[i].x) - map + 1],
45         ++Y[std::lower_bound(map, map + tot, t[i].y) - map + 1];
46     for (int i = 0, cnt, p; i < n; ++i) {
47         if (i && t[i].y == t[i - 1].y) {
48             ++cnt;
49             lnt a = ask(std::lower_bound(map, map + tot, t[i].x) - map);
50             lnt b = ask(std::lower_bound(map, map + tot, t[i - 1].x) - map + 1);
51             lnt d = c[cnt][m] * c[Y[std::lower_bound(map, map + tot, t[i].y) - map + 1] - cnt][m];
52             ans += d * (a - b);
53         } else cnt = 0;
54         p = std::lower_bound(map, map + tot, t[i].x) - map + 1;
55         add(p, -c[now[p]][m] * c[X[p] - now[p]][m]); ++now[p];
56         add(p, +c[now[p]][m] * c[X[p] - now[p]][m]);
57     }
58     printf("%lld\n", ((ans % mod) + mod) % mod);
59 }

 

@Author: YouSiki

 

posted @ 2017-01-03 14:46  YouSiki  阅读(190)  评论(0编辑  收藏  举报