BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*
BZOJ1227 SDOI2009 虔诚的墓主人
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棵
思路
首先离散化是肯定的,很容易证明如果在原图中存在的答案一定存在于离散化后的点上
然后我们考虑对这个东西进行处理
首先对于单独的一个位置[x,y],我们是可以算出四个值li,ri,ui,di分别表示以这个点为中心上下左右分别有多少个点有答案,所以我们考虑扫描线,每次统计一个区间的答案
但是我们又发现对于任何两个点[x1,y1][x2,y2]当满足y1=y2的时候对于任何的xk∈(x1,x2),都存在lx,rx相等
所以我们每一次只需要考虑一条线段就好了,同时我们维护需要维护的是一个区间的每个位置的C{ui,k}*C{di,k},在枚举线段的时候直接累加进去就可以了,同时记着把上一次的贡献给删掉,不然会后果很严重
然后又一个小技巧,因为这里是对2,147,483,648 取模,所以直接自然溢出就自动取模了
#include<bits/stdc++.h>
using namespace std;
#define LL unsigned int
#define N 1000010
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
#define lb(x) (x&(-x))
struct Node{int x,y;}p[N];
int n,m,w,k;
int prex[N],prey[N],sum[N];
int up[N],down[N];
LL t[N],c[N][];
vector<int> v[N];
bool cmp(Node a,Node b){
if(a.y==b.y)return a.x<b.x;
return a.y<b.y;
}
void add(int x,LL vl){for(;x<N;x+=lb(x))t[x]+=vl;}
LL query(int x){LL res=;for(;x;x-=lb(x))res+=t[x];return res;}
LL query(int l,int r){return query(r)-query(l-);}
void init(){
int len=max(n,m);
fu(i,,len)c[i][]=c[i][i]=;
fu(i,,len)
fu(j,,k)
c[i][j]=c[i-][j]+c[i-][j-];
}
int main(){
scanf("%d%d%d",&n,&m,&w);
fu(i,,w){
scanf("%d%d",&p[i].x,&p[i].y);
prex[i]=p[i].x;
prey[i]=p[i].y;
}
scanf("%d",&k);
sort(prex+,prex+w+);
sort(prey+,prey+w+);
int pre_x=unique(prex+,prex+w+)-prex-;
int pre_y=unique(prey+,prey+w+)-prey-;
n=pre_x;m=pre_y;
sort(p+,p+w+,cmp);
fu(i,,w){
p[i].x=lower_bound(prex+,prex+n+,p[i].x)-prex;
p[i].y=lower_bound(prey+,prey+m+,p[i].y)-prey;
v[p[i].y].push_back(i);
}
init();
fu(i,,n)sum[i]=;fd(i,w,)up[i]=sum[p[i].x],sum[p[i].x]++;
fu(i,,n)sum[i]=;fu(i,,w)down[i]=sum[p[i].x],sum[p[i].x]++;
LL ans=;
fu(i,,m){
int len=v[i].size();
fu(j,,len-){
int id=v[i][j];
add(p[id].x,c[up[id]][k]*c[down[id]+][k]-c[up[id]+][k]*c[down[id]][k]);
if(j)ans+=c[j][k]*c[len-j][k]*query(p[v[i][j-]].x+,p[id].x-);
}
}
printf("%d",ans&);
return ;
}
BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*的更多相关文章
- [luogu2154 SDOI2009] 虔诚的墓主人(树状数组+组合数)
传送门 Solution 显然每个点的权值可以由当前点上下左右的树的数量用组合数\(O(1)\)求出,但这样枚举会T 那么我们考虑一段连续区间,对于一行中两个常青树中间的部分左右树的数量一定,我们可用 ...
- Bzoj 1227: [SDOI2009]虔诚的墓主人 树状数组,离散化,组合数学
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 895 Solved: 422[Submit][Statu ...
- P2154 [SDOI2009]虔诚的墓主人 树状数组
https://www.luogu.org/problemnew/show/P2154 题意 在一个坐标系中,有w(1e5)个点,这个图中空点的权值是正上,正下,正左,正右各取k个的排列组合情况.计算 ...
- BZOJ-1227 虔诚的墓主人 树状数组+离散化+组合数学
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MB Submit: 914 Solved: 431 [Submit][Statu ...
- poj 3321:Apple Tree(树状数组,提高题)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18623 Accepted: 5629 Descr ...
- hdu 1541/poj 2352:Stars(树状数组,经典题)
Stars Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- [BZOJ1227][SDOI2009]虔诚的墓主人 组合数+树状数组
1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 1433 Solved: 672[Submit][Stat ...
- bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)
传送门 首先,对于每一块墓地,如果上下左右各有$a,b,c,d$棵树,那么总的虔诚度就是$C_k^a*C_k^b*C_k^c*C_k^d$ 那么我们先把所有的点都给离散,然后按$x$为第一关键字,$y ...
- BZOJ1227 [SDOI2009]虔诚的墓主人 【树状数组】
题目 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地.为 ...
随机推荐
- NPM Scripts -- onchange parallelshell
Watch for changes to the styles.scss file and automatically compile it to the css file. Run multiple ...
- C# Page基础功能,用于各页面继承
IBasePage.cs文件 /// <summary> /// 用于页面或用户控件 /// </summary> public interface IBasePage { / ...
- How to implement multiple constructor with different parameters in Scala
Using scala is just another road, and it just like we fall in love again, but there is some pain you ...
- Redis可以做哪些事儿?
Redis可以作为数据库,提供高速缓存,消息队列等功能,这里介绍Redis可以做的其中两件事: 1.提供缓存功能,作为缓存服务器; 2.轻量级的消息队列(MQ)进行使用. /// <summar ...
- pg按日,周,月进行数据统计
pg数据库按周,月统计数据 SELECT date_trunc('WEEK', insert_time) as insertDate, SUM(data_increment) as dataTotal ...
- SSM配置Socket多线程编程(RFID签到实例)
1.SocketServiceLoader.java package cn.xydata.pharmacy.api.app.test; import javax.servlet.ServletCont ...
- uva10766生成树计数
此类题是给定一个无向图,求所有生成树的个数,生成树计数要用到Matrix-Tree定理(Kirchhoff矩阵-树定理) G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0:当i ...
- day24 Restful api 设计和CRM 客户关系管理
博客: Restful: http://www.cnblogs.com/alex3714/articles/6808013.html http://www.cnblogs.com/alex3714/a ...
- python面试题包含基础和Linux操作以及数据库相关
今天面试了一家公司,感觉表现的不是很好,记录一下面试的试题. python基础部分 python 是一门什么样的语言面向对象的语言有那些,python的面向对象和Java面向对象的区别 Python是 ...
- CSS技巧和经验
如何清除图片下方出现几像素的空白间隙 方法1 img { display: block; } 方法2 除了top值,还可以设置为text-top | middle | bottom | text-bo ...