BZOJ-1227 虔诚的墓主人 树状数组+离散化+组合数学

来源:互联网 发布:mac向u盘复制文件 编辑:程序博客网 时间:2024/05/03 13:46

1227: [SDOI2009]虔诚的墓主人
Time Limit: 5 Sec Memory Limit: 259 MB
Submit: 914 Solved: 431
[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。 对于30%的数据,满足1 ≤ N, M ≤ 1,000。对于60%的数据,满足1 ≤ N, M ≤ 1,000,000。对于100%的数据,满足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。

Source

题解: 一看数据范围,肯定要离散化,熟练的打上,然后开始做。 这里要用到组合来进行求值,大体上的思路是: 如果a,b在同一行,则ans+=c(l[a]+1(包括a),k)*c(r[b]+1,k)再分别乘上ab间的每一个点的c(u[i],k)*c(d[i],k)
l[a],r[a],u[a],d[a]表示一个点上下左右的点数,可以预处理,也可以边做边记录
需要优化时间复杂度,于是要用树状数组维护a到b所有点的c(u[i],k)*c(d[i],k)之和
从左往右处理某行的某一个点时,要将树状数组中该点横坐标位置上的数进行修改
修改的值为就是现在的c(u[i],k)*c[d[i],k]减去原来的,也就是c(u[i],k)*c[d[i],k]-c(u[i]+1,k)*c[d[i]-1,k]

后来发现自己的离散似乎有些不适合,只能1AC19WA,于是改成黄学长的方式才能过

code:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int read(){    int x=0,f=1; char ch=getchar();    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}    return x*f;}#define maxw 100010#define p 2147483648LLint n,m,w,k,l;struct data{    int x,y;    bool operator < (const data & A) const        {            if (y==A.y) return x<A.x;            return y<A.y;        }}tr[maxw];long long tree[maxw*2],C[maxw*2][15],ans;int ls[maxw*2],cnt,num,now[maxw*2];int xx[maxw*2],yy[maxw*2];int lowbit(int x){    return x&(-x);}void add(int x,int dat){    for (int i=x; i<=w*2; i+=lowbit(i)) tree[i]=(tree[i]+dat)%p;}long long query(int x){    long long re=0;    for (int i=x; i>0; i-=lowbit(i)) re=(re+tree[i])%p;    return re;}int getloc(int dat){    int l=1,r=cnt;    while (l<=r)        {            int mid=(l+r)>>1;            if (ls[mid]<dat) l=mid+1;            else if (ls[mid]>dat) r=mid-1;            else return mid;                    }}void getC(){    C[0][0]=1;    for (int i=1; i<=w; i++)        {            C[i][0]=1;            for (int j=1; j<=min(k,i); j++)                C[i][j]=(C[i-1][j]+C[i-1][j-1])%p;        }}int main(){    n=read(),m=read();    w=read();    for (int i=1; i<=w; i++) ls[++cnt]=tr[i].x=read(),ls[++cnt]=tr[i].y=read();    k=read();    sort(ls+1,ls+cnt+1);    //for (int i=2; i<=cnt; i++) if (ls[i]!=ls[i-1]) ls[++num]=ls[i];    //for (int i=1; i<=w; i++) tr[i].x=getloc(tr[i].x),tr[i].y=getloc(tr[i].y);    for (int i=1; i<=w; i++) xx[getloc(tr[i].x)]++,yy[getloc(tr[i].y)]++;    getC(); sort(tr+1,tr+w+1);    //for (int i=1; i<=w; i++)        //printf("%d %d\n",getloc(tr[i].x),getloc(tr[i].y));    for(int i=1;i<=w;i++)        {            if(i>1 && tr[i].y==tr[i-1].y)                l++,ans+=(query(getloc(tr[i].x)-1)-query(getloc(tr[i-1].x)))*(C[l][k]*C[yy[getloc(tr[i].y)]-l][k]),ans%=p;            else l=0;            int loc=getloc(tr[i].x); now[loc]++;            int delta=(C[now[loc]][k]*C[xx[loc]-now[loc]][k]-C[now[loc]-1][k]*C[xx[loc]-now[loc]+1][k])%p;            add(loc,delta);        }    if (ans<0) ans+=p;     printf("%lld\n",ans);    return 0;} 
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两颗牙中间黑了怎么办 牙齿酸痛怎么办才能好 牙齿被磨小了疼怎么办 牙齿有黑点蛀牙怎么办 小孩有蛀牙牙痛怎么办 牙齿修补后疼痛怎么办 腹部绞痛出冷汗怎么办 结石运动后尿血怎么办 透析病人尿血该怎么办 宝宝吃药就吐怎么办 肚子坠胀尿血怎么办 透析病人回来血尿怎么办 血尿腹痛腰疼怎么办 新诺明 吃多了 怎么办 吃下火药拉肚子怎么办 打哈欠停不下来怎么办 小孩一直咳不停怎么办 孩子咳嗽咳不停怎么办 孩子咳嗽出冷汗怎么办 宝宝一直咳不停怎么办 尿血右上腹疼怎么办 尿道感染尿出血怎么办 儿童血尿腹痛是怎么办 肚子胀痛拉二天血尿怎么办 小牛肚尿道发炎怎么办 吃奶小牛涨肚怎么办 尿路感染尿出血了怎么办 尿血还带血块怎么办 尿道感染尿血了怎么办 老人小便带血怎么办 胎儿双肾盂扩张怎么办 宝宝发烧后血尿怎么办 孕妇肾盂分离16怎么办 急性尿道炎尿血严重怎么办 尿急尿频尿血严重怎么办 打预防针两天后发烧怎么办 孩子发烧心跳快怎么办 拉肚子脱水人犯困怎么办 拉肚子拉脱水了怎么办 孕妇肚子疼拉水怎么办 腹泻拉脱水了怎么办