列表

详情


NC20330. [SDOI2009]虔诚的墓主人

描述

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

输入描述

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

输出描述

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

示例1

输入:

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

输出:

6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 111ms, 内存消耗: 12248K, 提交时间: 2019-03-16 11:41:56

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> a[100010];
int n,m,k,mx,my,
tx[100010],ty[100010],ordx[100010],ordy[100010],
s[200010],downc[100010],upc[100010],
c[100010][15];
void add(int p,int x)
{
    for (int k=p;k<=my;k+=k&-k) s[k]+=x;
}
int qry(int l,int r)
{
    int ret=0;
    for (int k=r-1;k;k-=k&-k) ret+=s[k];
    for (int k=l;k;k-=k&-k) ret-=s[k];
    return ret;
}
int main()
{
    /*freopen("in.txt","r",stdin);*/
    int x,y,ans=0;
    scanf("%*d%*d%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&tx[i],&ty[i]);
        ordx[i]=tx[i];
        ordy[i]=ty[i];
    }
    scanf("%d",&k);
    for (int i=0;i<=n;i++) c[i][0]=1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=i&&j<=k;j++)
            c[i][j]=c[i-1][j]+c[i-1][j-1];
    sort(ordx+1,ordx+n+1);
    sort(ordy+1,ordy+n+1);
    mx=unique(ordx+1,ordx+n+1)-ordx-1;
    my=unique(ordy+1,ordy+n+1)-ordy-1;
    for (int i=1;i<=n;i++)
    {
        x=lower_bound(ordx+1,ordx+mx+1,tx[i])-ordx;
        y=lower_bound(ordy+1,ordy+my+1,ty[i])-ordy;
        a[x].push_back(y);
    }
    for (int i=1;i<=mx;i++)
        for (int j=0;j<a[i].size();j++)
            downc[a[i][j]]++;
    for (int i=1;i<=mx;i++)
    {
        sort(a[i].begin(),a[i].end());
        for (int j=0;j<a[i].size();j++)
        {
            y=a[i][j];
            add(y,c[upc[y]][k]*(-c[downc[y]][k]+c[downc[y]-1][k]));
            downc[y]--;
        }
        for (int j=0;j<a[i].size()-1;j++)
            ans+=c[j+1][k]*c[a[i].size()-j-1][k]*qry(a[i][j],a[i][j+1]);
        for (int j=0;j<a[i].size();j++)
        {
            y=a[i][j];
            add(y,c[downc[y]][k]*(-c[upc[y]][k]+c[upc[y]+1][k]));
            upc[y]++;
        }
    }
    printf("%d\n",ans&2147483647);
}

上一题