ACM-ICPC 2018 南京赛区网络预赛 The writing on the wall (数学思想+DP维护)*

Feeling hungry, a cute hamster decides to order some take-away food (like fried chicken for only 303030 Yuan).

However, his owner CXY thinks that take-away food is unhealthy and expensive. So she demands her hamster to fulfill a mission before ordering the take-away food. Then she brings the hamster to a wall.

The wall is covered by square ceramic tiles, which can be regarded as a n∗mn * mn∗m grid. CXY wants her hamster to calculate the number of rectangles composed of these tiles.

For example, the following 3∗33 * 33∗3 wall contains 363636 rectangles:

Such problem is quite easy for little hamster to solve, and he quickly manages to get the answer.

Seeing this, the evil girl CXY picks up a brush and paint some tiles into black, claiming that only those rectangles which don't contain any black tiles are valid and the poor hamster should only calculate the number of the valid rectangles. Now the hamster feels the problem is too difficult for him to solve, so he decides to turn to your help. Please help this little hamster solve the problem so that he can enjoy his favorite fried chicken.

Input

There are multiple test cases in the input data.

The first line contains a integer TTT : number of test cases. T≤5T \le 5T≤5.

For each test case, the first line contains 333 integers n,m,kn , m , kn,m,k , denoting that the wall is a n×mn \times mn×m grid, and the number of the black tiles is kkk.

For the next kkk lines, each line contains 222 integers: x yx\ yx y ,denoting a black tile is on the xxx-th row and yyy-th column. It's guaranteed that all the positions of the black tiles are distinct.

For all the test cases,

1≤n≤105,1≤m≤1001 \le n \le 10^5,1\le m \le 1001≤n≤105,1≤m≤100,

0≤k≤105,1≤x≤n,1≤y≤m0 \le k \le 10^5 , 1 \le x \le n, 1 \le y \le m0≤k≤105,1≤x≤n,1≤y≤m.

It's guaranteed that at most 222 test cases satisfy that n≥20000n \ge 20000n≥20000.

Output

For each test case, print "Case #xxx: ansansans" (without quotes) in a single line, where xxx is the test case number and ansansans is the answer for this test case.

Hint

The second test case looks as follows:

样例输入复制

2
3 3 0
3 3 1
2 2

样例输出复制

Case #1: 36
Case #2: 20

题目来源

ACM-ICPC 2018 南京赛区网络预赛

代码高亮 Sublime Vim Emacs

环境配色亮色配色暗色配色 暗色配色

返回

  • 亮色配色
  • 暗色配色

代码缩进248 4

返回

  • 2
  • 4
  • 8

C 语言C++ 语言 (C++11)Java 语言 C++ 语言 (C++11)

返回

  • C 语言
  • C++ 语言 (C++11)
  • Java 语言
  • main.cpp

通用

逻辑

循环

数学

文本

列表

颜色

变量

函数

 

 

57

    }

1

#pragma comment(linker, "/STACK:102400000,102400000")

2

#include<bits/stdc++.h>

3

using namespace std;

4

5

#define debug puts("YES");

6

#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

7

8

#define lrt int l,int r,int rt

9

#define lson l,mid,rt<<1

10

#define rson mid+1,r,rt<<1|1

11

#define ll long long

12

13

const int  maxn =1e5+5;

14

const int mod=1e9+7;

15

16

ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); }

17

ll powmod(ll x,ll y){ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}

18

19

int mp[maxn][105];

20

int mark[105];

21

int n,m,k,x,y;

22

ll cnt;

23

24

int main()

25

{

26

    int t;scanf("%d",&t);

27

    for(int ca=1;ca<=t;ca++)

28

    {

29

        memset(mark,0,sizeof(mark));

30

        memset(mp,0,sizeof(mp));

31

 

关闭终端 终端 - 计蒜客

已通过 0 组测试数据,共 5 组

 

只看题面

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long

const int  maxn =1e5+5;
const int mod=1e9+7;

ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); }
ll powmod(ll x,ll y){ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
/*
题目大意:数学题,求有限制的矩形的符合要求的小矩形数量。

赤裸裸的数学思维+DP。
从低维到高维考虑并思考它的计数方法。
首先如果只有一行,答案是等差数列和的形式,
两层循环很简单,如果维数多了一维,
那么给定一个高度增量,就是上一个一维的不是权重都为1嘛,
那么二维的话权重是高度一维的值,也就是h。
三层循环。

至此数学框架已经被提取出来了,下面思考
带有限制点的方案数,,在权重累加到答案的时候,
高维权重是关于高度的线性函数,
那么在每一次固定一端然后扫描到另一端的过程中,
动态维护一个权重,每次累加其合法的最小值即可,
或许结合图形想更加形象。

结合代码,在行的推进过程中,
高度数组可以迭代使用,那么
每次扫描就可以利用其和行做差更新权重值。
*/

int mp[maxn][105];
int mark[105];
int n,m,k,x,y;
ll cnt;

int main()
{
    int t;scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        memset(mark,0,sizeof(mark));
        memset(mp,0,sizeof(mp));

        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<k;i++)
        {
            scanf("%d%d",&x,&y);
            mp[x][y]=1;
        }

        cnt=0;
        for(int h=1;h<=n;h++)
        {
            for(int i=1;i<=m;i++) if(mp[h][i]==1) mark[i]=h;
            for(int i=1;i<=m;i++)///i列
            {
                int minn=1000000;
                for(int j=i;j<=m;j++)///j列
                {
                    minn=min(minn,h-mark[j]);///在h行i列位置上,最高的那个格子是什么高度
                    cnt+=1LL*minn;
                }
            }
         }
         printf("Case #%d: %lld\n",ca,cnt);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值