【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; }
波澜前,面不惊。