bzoj-1227 虔诚的墓主人

来源:互联网 发布:如何看k线图 知乎 编辑:程序博客网 时间:2024/04/30 22:36

题意:

在一个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 2147483647using 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 2147483648llusing 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++;elsetempy[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); elseupdate(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;}


1 0