BUPT2017 wintertraining(15) #9

下面不再说明题意了请自行读题,直接放contest链接。

https://vjudge.net/contest/151607

 

A.考虑当火车隔k站一停时

区间长度 >= k 的纪念品一定能买到

区间长度 <k 的纪念品最多覆盖一个停靠的站点

求出 n / k 个点, 每个点上覆盖的纪念品数累加即可

k 从 1 到 m 都需要求

我们只要把纪念品按区间长度排序

然后向后扫就可以了

总复杂度 O(nlog^2n)

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 #define lowbit(x) (x&(-x))
 5 
 6 using std::sort;
 7 
 8 const int maxn = 300010;
 9 
10 int n, m, c[maxn];
11 
12 struct node {
13     int l, r, len;
14     bool operator < (const node &a) const {
15         return len < a.len;
16     }
17 }a[maxn];
18 
19 void add(int i, int x) {
20     while(i <= m) c[i] += x, i += lowbit(i);
21 }
22 
23 int ask(int i) {
24     int ret = 0;
25     while(i > 0) ret += c[i], i -= lowbit(i);
26     return ret;
27 }
28 
29 int main() {
30     scanf("%d %d", &n, &m);
31     for(int i = 1;i <= n;i ++) {
32         scanf("%d %d", &a[i].l, &a[i].r);
33         a[i].r ++, a[i].len = a[i].r - a[i].l;
34     }
35     sort(a + 1, a + n + 1);
36     for(int i = 1, j = 1, ans;i <= m;i ++) {
37         while(j <= n && a[j].len < i) {
38             add(a[j].l, 1);
39             add(a[j].r, -1);
40             j ++;
41         }
42         ans =  n - j + 1;
43         for(int k = i;k <= m;k += i)
44             ans += ask(k);
45         printf("%d\n", ans);
46     }
47 }
View Code

 

B.一个暴力理论向上约等于O(n^3)的做法:

我们把原矩阵旋转45度,再扔掉那些对当前点贡献为0的点

就能得到一个对当前点有贡献的正方形点阵

从外到里,贡献系数递增

所以我们的做法就是枚举点,然后O(k)计算它的 f 函数值...

下面代码把 scanf 改成快读卡常数就能过了...

 1 #include <cstdio>
 2 
 3 #define rep(i, j, k) for(int i = j;i <= k;i ++)
 4 
 5 long long s[2100][2100], ans = -1, tmp;
 6 
 7 int n, m, k, t, p, q, ax, ay;
 8 
 9 int main() {
10     scanf("%d %d %d", &n, &m, &k);
11     rep(i, 1, n) rep(j, 1, m) {
12         scanf("%d", &t);
13         s[i + j - 1][i - j + m] = t;
14     }
15     rep(i, 1, n + m - 1) rep(j, 1, m + n - 1) 
16         s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
17     rep(i, k, n + 1 - k) rep(j, k, m + 1 - k) {
18         tmp = 0, p = i + j - 1, q = i - j + m;
19         rep(r, 0, k - 1) tmp += s[p + r][q + r] - s[p - r - 1][q + r] - s[p + r][q - r - 1] + s[p - r - 1][q - r - 1];
20         if(tmp > ans) ans = tmp, ax = i, ay = j;
21     }    
22     printf("%d %d", ax, ay);
23     return 0;
24 }
View Code

 

转载于:https://www.cnblogs.com/ytytzzz/p/6515851.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值