题目中矩形的尺寸太大,导致墓地的数目太多,如果我们统计每一个墓地的虔诚度,超时是一定的。

而常青树的数目<=1e5.这启发我们从树的方向去思考。

考虑一行没有树的情况,显然这一行的墓地的虔诚度之和为0.也就是说我们可需要考虑常青树在的行就行了。

对于在同一行的每两颗长青树之间,墓地的虔诚度之和为C(l,k)*C(r,k)*sigma(C(up,k)*C(under,k)).这里的l是左边的这棵树的左边有多少颗树,r同理。up则是这一段的每个墓地上面有多少颗树,under同理。对于求和,我们可以用树状数组logn的时间查询。

而扫描完一颗树的时候,需要更新C(up,k)*C(under,k).因为树的数目<=1e5,所以总复杂度不过O(n*logn).

所以我们只需要预处理出组合数,然后离散化x坐标,再一行一行的利用BIT查询并更新。

这里的一个优化常数的小技巧是:由于题目要求对1<<31取模,中途过程中可以让int自然溢出,最后的答案mod((1<<31)-1)即可。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi 3.1415926535
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int res=, flag=;
char ch;
if((ch=getchar())=='-') flag=;
else if(ch>=''&&ch<='') res=ch-'';
while((ch=getchar())>=''&&ch<='') res=res*+(ch-'');
return flag?-res:res;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct Node{int x, y;}node[N];
int C[N][], tree[N], siz, col[N], now[N];
VI v;
vector<PII> vv; bool comp(Node a, Node b){
if (a.y==b.y) return a.x<b.x;
else return a.y<b.y;
}
void init(){
FOR(i,,) C[i][]=;
FOR(i,,) FOR(j,,) C[i][j]=C[i-][j]+C[i-][j-];
}
void add(int x, int val){while (x<=siz) tree[x]+=val, x+=lowbit(x);}
int query(int x){
int res=;
while (x) res+=tree[x], x-=lowbit(x);
return res;
}
int cal(int x, int y){return x<y?:C[x][y];}
int main ()
{
init();
int n, m, T, k, ans=;
n=Scan(); m=Scan(); T=Scan();
FOR(i,,T) node[i].x=Scan(), node[i].y=Scan(), v.pb(node[i].x);
k=Scan();
sort(node+,node+T+,comp);
sort(v.begin(),v.end());
siz=unique(v.begin(),v.end())-v.begin();
FOR(i,,T) {
node[i].x=lower_bound(v.begin(),v.begin()+siz,node[i].x)-v.begin()+;
++col[node[i].x];
}
int i=;
while (i<=T) {
vv.clear();
vv.pb(mp(node[i].x,node[i].y));
++i;
while (i<=T&&node[i].y==node[i-].y) vv.pb(mp(node[i].x,node[i].y)), ++i;
int ss=vv.size();
if (ss>k) FOR(j,k,ss-k) {
ans+=(C[j][k]*C[ss-j][k]*(query(vv[j].first-)-query(vv[j-].first)));
}
FO(j,,ss) {
int fi=vv[j].first;
add(fi,-*cal(now[fi],k)*cal(col[fi]-now[fi],k));
++now[fi];
add(fi,cal(now[fi],k)*cal(col[fi]-now[fi],k));
}
}
printf("%d\n",ans&);
return ;
}

BZOJ 1227 虔诚的墓主人(离散化+树状数组)的更多相关文章

  1. luogu2154 [SDOI2009] 虔诚的墓主人 离散化 树状数组 扫描线

    题目大意 公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.一块墓地的虔诚度是指以这块墓地为中心的十字架的数目,一个十字架可以看成中间是墓地,墓地的正上.正 ...

  2. [BZOJ1227][SDOI2009]虔诚的墓主人 组合数+树状数组

    1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec  Memory Limit: 259 MBSubmit: 1433  Solved: 672[Submit][Stat ...

  3. BZOJ1227 [SDOI2009]虔诚的墓主人 【树状数组】

    题目 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地.为 ...

  4. 【Luogu】P2154虔诚的墓主人(树状数组)

    题目链接 这题就是考虑我们有这样一个情况

  5. bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)

    传送门 首先,对于每一块墓地,如果上下左右各有$a,b,c,d$棵树,那么总的虔诚度就是$C_k^a*C_k^b*C_k^c*C_k^d$ 那么我们先把所有的点都给离散,然后按$x$为第一关键字,$y ...

  6. BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*

    BZOJ1227 SDOI2009 虔诚的墓主人 Description 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. ...

  7. BZOJ 1818 内部白点(离散化+树状数组)

    此题就是1227 的弱化版. 画个图或者稍微证明一下就能够知道,一定不会超过一次变换. 那么我们只需要统计有多少个白点会变黑,换句话说就是有多少个白点上下左右都有黑点. 离散化横坐标,因为没有黑点在的 ...

  8. CodeForces 540E - Infinite Inversions(离散化+树状数组)

    花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树 ...

  9. Ultra-QuickSort(归并排序+离散化树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 50517   Accepted: 18534 ...

随机推荐

  1. Git Status 中文乱码解决

    现象: jb@H39:~/doc$ git statusOn branch masterYour branch is up-to-date with 'origin/master'. Untracke ...

  2. services 系统服务的启动、停止、卸载

    MySQL服务的启动.停止与卸载 在 Windows 命令提示符下运行: 启动: net start MySQL 停止: net stop MySQL 卸载: sc delete MySQL Sc d ...

  3. 北京Uber优步司机奖励政策(12月10日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. HttpClient&Jsoup爬虫的简单应用

    详细的介绍已经有很多前辈总结,引用一下该篇文章:https://blog.csdn.net/zhuwukai/article/details/78644484 下面是一个代码的示例: package ...

  5. ORB-SLAM(九)LocalMapping

    LocalMapping作用是将Tracking中送来的关键帧放在mlNewKeyFrame列表中:处理新关键帧,地图点检查剔除,生成新地图点,Local BA,关键帧剔除.主要工作在于维护局部地图, ...

  6. 一文带你了解 Raft 一致性协议的关键点

    此文已由作者孙建良授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Raft 协议的发布,对分布式行业是一大福音,虽然在核心协议上基本都是师继 Paxos 祖师爷(lampor ...

  7. beauifulsoup模块的介绍

    01   爬虫基础知识介绍 相关库:1.requests,re  2.BeautifulSoup   3.hackhttp 使用requests发起get,post请求,获取状态码,内容: 使用re匹 ...

  8. Objective-C 类和对象

    面向对象 面向对象(Object-Oriented)是基于面向过程(procedure-oriented)而言的 面向对象 强调对象<指挥者> OC, Java语言就是面向对象 面向过程 ...

  9. 域名、IP地址、URL关系

    域名是个文字形式记录的IP地址 IP地址是计算机在网络中的门牌号! URL是网页地址 例如1: http://zhidao.baidu.com/question/14674128.html 是URL ...

  10. 《Effective C++》读书笔记 资源管理

    C++程序中最常用的资源包括动态分配的内存,文件描述器,互斥锁,数据库连接,网络socket等等.不论哪种资源,重要的是,当你不再使用他时,必须将他归还给系统. 一个很好的做法是以对象管理资源.把资源 ...