【BZOJ1227】[SDOI2009]虔诚的墓主人
E. 虔诚的墓主人
题目描述
输入格式
输出格式
样例
数据范围与提示
树状数组+离散化+组合数
真的是个神仙题,主要是代码打得太乱(逢离散化必挂),颓了测试点才调出来…
M,N远大于W,铁定要离散化,然后W2其实就可以AC了(数据有点水啊),但是是可以被卡掉的,

对于一个墓地,设他的上下左右分别有u[],d[],l[],r[]颗树,则他的虔诚度=C(u,k)*C(d,k)*C(l,k)*C(r,k),
对于同一行两颗常青树a,b之间的空地,他们的l[]和r[]是一样的,所以可以考虑用树状数组维护这一行的每个点C(u,k)*C(d,k)的前缀和,
ans+=C(l[a]+1,k)*C(r[b]+1,k)*(ask(b-1)-ask(a)),换行时单点修改即可。
#include<map>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define mod 2147483648
#define ma(x) memset(x,0,sizeof(x))
using namespace std;
LL N,M,W,k;
LL C[100010][15];
LL xi[100010],yi[100010],tx[100010],ty[100010];
LL h[100010],l[100010];
LL ss[100010],xx[100010];
LL maxx,maxy;
vector<int> inc[100010];
LL Ch[100100];
int lowbit(int x){return x&(-x);}
void add(int x,LL y);
LL ask(int x);
void xget_C(int maxn);
signed main()
{
// freopen("25.in","r",stdin);
scanf("%lld%lld%lld",&N,&M,&W);
for(int i=1;i<=W;i++)scanf("%d%d",&xi[i],&yi[i]),tx[i]=xi[i],ty[i]=yi[i];
cin>>k;
xget_C(100000);
sort(xi+1,xi+W+1);
maxx=unique(xi+1,xi+W+1)-xi-1;
sort(yi+1,yi+W+1);
maxy=unique(yi+1,yi+W+1)-yi-1;
for(int i=1;i<=W;i++)
{
int t1=lower_bound(xi+1,xi+maxx+1,tx[i])-xi;
int t2=lower_bound(yi+1,yi+maxy+1,ty[i])-yi;
h[t2]++,l[t1]++;
inc[t2].push_back(t1);
}
for(int i=1;i<=maxy;i++)
sort(inc[i].begin(),inc[i].end());
for(int i=1;i<=maxx;i++)ss[i]=l[i];
LL ans=0;
for(int i=1;i<=maxy;i++)
{
for(int j=0;j<inc[i].size();j++)
{
ss[inc[i][j]]--,xx[inc[i][j]]++;
LL te1=(C[ss[inc[i][j]]][k]*C[xx[inc[i][j]]][k])%mod,
te2=(C[ss[inc[i][j]]+1][k]*C[xx[inc[i][j]]-1][k])%mod;
add(inc[i][j],(te1-te2+mod)%mod);
}
if(i>k && h[i]>=2*k)
for(int j=k;j+k<=inc[i].size();j++)
if(j && inc[i][j]!=inc[i][j-1]+1)
ans=(ans+C[j][k]*C[inc[i].size()-j][k]*(ask(inc[i][j]-1)-ask(inc[i][j-1])))%mod;
}
cout<<(ans%mod+mod)%mod<<endl;
}
void xget_C(int maxn)
{
C[0][0]=1;
for(int i=1;i<=maxn;i++)
{
C[i][0]=1;
for(int j=1;j<=min(i,11);j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
void add(int x,LL y)
{
while(x<=maxx)
{
Ch[x]=(Ch[x]+y)%mod;
x+=lowbit(x);
}
}
LL ask(int x)
{
LL ans=0;
while(x)
{
ans=(ans+Ch[x])%mod;
x-=lowbit(x);
}
return ans;
}
波澜前,面不惊。

浙公网安备 33010602011771号
ヾ(≧O≦)〃嗷~