题意:
在一个nxm的矩形里给出一些w个点,这些是常青树的坐标;
求所有空地上下左右能组成的长度为k的十字架的总数;
1<=n,m<=10^9,1<=w<=100000,1<=k<=10
题解:
这道题思路很简单,就是代码不太好写;
首先如果是上下左右都没有树的点是必然没有虔诚度的,所以我们可以肆无忌惮的离散化一下;
然后对于一块墓地,它的答案就是C ( l , k ) *C ( r , k ) *C ( u , k ) *C ( d , k );
(这里的l,r,u,d分别指某个点左右上下的常青树个数)
显然枚举每一块墓地是超时的,那么就考虑一次计算多个墓地;
对于在同一行两棵树之间的墓地来说,它们的 C ( l , k ) *C ( r , k )是相同的;
答案就是C ( l , k ) *C ( r , k ) * ∑C( u[i] , k )*C( d[i] , k );
求和的维护自然是树状数组,那么整道题的思路也就有了;
把所有树按行来排序,然后遍历维护出每棵树的l,r,u,d;
维护树状数组然后处理答案,时间复杂度是常数巨大的O(nlogn);
(代码写的非常非常烂。。。3900+ms我都不太好意思贴。。。
更新: 15/07/21
今天考试碰上原题。。。
怒切之后发现有点黑科技可以用;
mod的数恰好是1<<31所以让int自然溢出就好;
最后输出答案就是&(1<<31-1)就是答案;
这样搞之后时间就是1864 ms啦;
代码:
15/07/21版:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define mod 2147483647
using namespace std;
struct node
{
int x,y,tx,l,r,u,d;
bool is;
}a[N];
int C[N][15];
int dis[N],tree[N],hash[N],last[N];
int cmp(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
int lowbit(int x)
{
return x&(-x);
}
void init()
{
for(int i=0;i<N;i++)
{
C[i][0]=1;
for(int j=1;j<=min(i,10);j++)
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}
void add(int x,int val)
{
while(x<N)
{
tree[x]+=val;
x+=lowbit(x);
}
}
int query(int x)
{
int ret=0;
while(x)
{
ret+=tree[x];
x-=lowbit(x);
}
return ret;
}
int main()
{
freopen("cross.in","r",stdin);
freopen("cross.out","w",stdout);
int n,m,i,j,k,K,x,y,w,len,ans;
init();
scanf("%d%d%d",&n,&m,&w);
for(i=1;i<=w;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
dis[i]=a[i].x;
}
scanf("%d",&K);
sort(dis+1,dis+w+1);
len=unique(dis+1,dis+w+1)-dis-1;
sort(a+1,a+w+1,cmp);
for(i=1,y=-1,k=0;i<=w;i++)
{
if(a[i].y!=y)
y=a[i].y,k=0;
a[i].l=k;
k++;
a[i].tx=lower_bound(dis+1,dis+len+1,a[i].x)-dis;
a[i].d=hash[a[i].tx];
hash[a[i].tx]++;
if(a[last[a[i].tx]].y+1==a[i].y)
a[last[a[i].tx]].is=1;
last[a[i].tx]=i;
}
for(i=w,y=-1,k=0;i>=1;i--)
{
if(a[i].y!=y)
y=a[i].y,k=0;
a[i].r=k;
k++;
a[i].u=hash[a[i].tx]-a[i].d-1;
}
for(i=1,y=-1,ans=0;i<=w;i++)
{
if(a[i].is!=1)
add(a[i].tx,C[a[i].u][K]*C[a[i].d+1][K]-(query(a[i].tx)-query(a[i].tx-1)));
if(a[i].y==a[i+1].y)
ans+=C[a[i].l+1][K]*C[a[i+1].r+1][K]*(query(a[i+1].tx-1)-query(a[i].tx));
}
printf("%d",(ans)&mod);
return 0;
}
旧版:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define mod 2147483648ll
using namespace std;
typedef long long ll;
struct node
{
ll dx,dy,x,y,l,r,u,d;
bool is;
}a[N];
ll disx[N],disy[N];
ll tempx[N],tempy[N];
ll C[N][20],q[N];
ll tree[N];
int cmpll(ll a,ll b)
{
return a<b;
}
int cmpnode(node a,node b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
ll mul(ll x,ll y)
{
ll ret=0;
while(y)
{
if(y&1)
ret=(ret+x)%mod;
x=(x+x)%mod;
y>>=1;
}
return ret;
}
ll lowbit(ll k)
{
return k&(-k);
}
void update(ll k,ll val)
{
while(k<=100000)
{
tree[k]=(tree[k]+val)%mod;
k+=lowbit(k);
}
}
ll query(ll k)
{
ll ret=0;
while(k)
{
ret=(ret+tree[k])%mod;
k-=lowbit(k);
}
return ret;
}
int main()
{
ll n,m,w,i,j,k,x,y,cnt,lenx,leny,ans,st,en;
scanf("%lld%lld%lld",&n,&m,&w);
for(i=1;i<=w;i++)
{
scanf("%lld%lld",disx+i,disy+i);
a[i].x=disx[i],a[i].y=disy[i];
}
scanf("%lld",&k);
sort(disx+1,disx+1+w,cmpll);
sort(disy+1,disy+1+w,cmpll);
lenx=unique(disx+1,disx+1+w)-disx-1;
leny=unique(disy+1,disy+1+w)-disy-1;
sort(a+1,a+w+1,cmpnode);
for(i=1,y=1,cnt=0;i<=w;i++)
{
a[i].dx=lower_bound(disx+1,disx+1+lenx,a[i].x)-disx;
a[i].dy=lower_bound(disy+1,disy+1+leny,a[i].y)-disy;
if(a[i].dy==y)
a[i].l=cnt++;
else
tempy[y]=cnt,a[i].l=0,cnt=1,y=a[i].dy;
a[i].d=tempx[a[i].dx];
tempx[a[i].dx]++;
}
tempy[a[w].dy]=cnt;
for(i=1;i<=w;i++)
{
a[i].u=tempx[a[i].dx]-a[i].d-1;
a[i].r=tempy[a[i].dy]-a[i].l-1;
}
st=1,en=0;
for(i=w,y=leny,x=w;i>0;i--)
{
if(a[i].dy!=y)
{
while(st<=en) st++;
for(j=x;j>i;j--)
q[++en]=a[j].dx;
x=i;
y=a[i].dy;
}
while(q[st]>a[i].dx&&st<=en) st++;
if(q[st]==a[i].dx) a[i].is=1;
}
for(i=0;i<=w;i++)
{
C[i][0]=1;
for(j=1;j<=min(i,k);j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
y=a[1].dy,x=1;
for(i=1,ans=0;i<=w;i++)
{
if(a[i].l+1>=k&&a[i].r>=k&&a[i+1].dx-1>a[i].dx)
{
ans=(ans+(((query(a[i+1].dx-1)-query(a[i].dx))%mod+mod)%mod)*
(C[a[i].l+1][k]*C[a[i].r][k]%mod))%mod;
}
if(a[i].is)
update(a[i].dx,((C[a[i].u-1][k]*C[a[i].d+1][k]%mod)-
((query(a[i].dx)-query(a[i].dx-1))%mod+mod)%mod+mod)%mod);
else
update(a[i].dx,((C[a[i].u][k]*C[a[i].d+1][k]%mod)-
((query(a[i].dx)-query(a[i].dx-1))%mod+mod)%mod+mod)%mod);
}
printf("%lld",ans%mod);
return 0;
}