bzoj-1227 虔誠的墓主人
題意:
在一個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;
}
相關推薦
BZOJ-1227 虔誠的墓主人 樹狀陣列+離散化+組合數學
1227: [SDOI2009]虔誠的墓主人 Time Limit: 5 Sec Memory Limit: 259 MB Submit: 914 Solved: 431 [Submit][Status][Discuss] Description
bzoj-1227 虔誠的墓主人
題意: 在一個nxm的矩形裡給出一些w個點,這些是常青樹的座標; 求所有空地上下左右能組成的長度為k的十字架的總數; 1<=n,m<=10^9,1<=w<=100000,1<=k<=10 題解: 這道題思路很簡單,就是程式碼不太好寫;
bzoj 1227: [SDOI2009]虔誠的墓主人
pro stream 存在 i++ namespace include div ont ans Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麽種著一棵常青樹,要麽是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基
BZOJ 1227 [SDOI2009]虔誠的墓主人 - 掃描線
getchar one 離散化 push_back 合數 getchar() owb str += Solution 離散化 掃描線, 並用 $rest[i]$ 和 $cnt[i]$ 記錄 第$i$列 總共有 $cnt[i]$棵常青樹, 還有$rest[i]$ 沒有被掃描
BZOJ 1227: [SDOI2009]虔誠的墓主人 數狀陣列
Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合適墓地。為了體現自己對主的真誠,他們希望自己的墓地擁
[bzoj]1227: [SDOI2009]虔誠的墓主人【樹狀陣列】
** Description ** 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合適墓地。為了體現自己對主的真誠,他們
BZOJ 1227: [SDOI2009]虔誠的墓主人 樹狀陣列 組合數
1227: [SDOI2009]虔誠的墓主人 Time Limit: 5 Sec Memory Limit: 259 MB Submit: 1324 Solved: 629 Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N
【bzoj 1227】虔誠的墓主人(樹狀陣列)
傳送門biu~ 上下左右沒有樹的墓地必然沒有虔誠度,所以將原圖離散化成一個最大為w×ww×w的圖。 對於每塊墓地,令在它上、下、左、右方向常青樹的數目分別為uu,pp,ll,rr。則以這個點為中心的
BZOJ1227: [SDOI2009]虔誠的墓主人
包含 lan mst tput lib main 數組 script 部分 1227: [SDOI2009]虔誠的墓主人 Time Limit: 5 Sec Memory Limit: 259 MBSubmit: 1306 Solved: 615[Submit][
BZOJ1227 [SDOI2009]虔誠的墓主人 【樹狀數組】
lag AI namespace flag pos 上下左右 OS 離散化 str 題目 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麽種著一棵常青樹,要麽是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合
Luogu 2154 [SDOI2009]虔誠的墓主人
分享 esp 我們 open index 一個空格 nod 狀態 nom 弄了很久,狀態很爛…… 首先發現可用的點一共只有$1e5$個,所以可以離散化坐標來方便計算。 發現對於一個空格,設它的上、下、左、右分別有$u, d, l, r$個點,
【BZOJ1227】[SDOI2009]虔誠的墓主人(線段樹)
方案 mod printf math std code tchar bre getchar 【BZOJ1227】[SDOI2009]虔誠的墓主人(線段樹) 題面 BZOJ 洛谷 題解 顯然發現答案就是對於每一個空位置,考慮上下左右各有多少棵樹,然後就是這四個方向上樹的數量中
[luogu2154 SDOI2009] 虔誠的墓主人(樹狀數組+組合數)
得到 sdoi2009 define lin 思路 fin size set new 傳送門 Solution 顯然每個點的權值可以由當前點上下左右的樹的數量用組合數\(O(1)\)求出,但這樣枚舉會T 那麽我們考慮一段連續區間,對於一行中兩個常青樹中間的部分左右樹的數量一
2018.10.25 bzo1227: [SDOI2009]虔誠的墓主人(組合數學+掃描線+bit)
傳送門 有點難調啊。其實是我自己sb了 不過交上去1A1A1A還是平衡了一下心態。 所以這道題怎麼做呢? 我們考慮對於一個點(x,y)(x,y)(x,y)如果這個點成為中心,正左/右/上/下分別有l/r
BZOJ1227 SDOI2009 虔誠的墓主人【樹狀陣列+組合數】【好題】*
BZOJ1227 SDOI2009 虔誠的墓主人 Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合
【SDOI2009】【BZOJ1227】虔誠的墓主人
Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合適墓地。為了體現自己對主的真誠,他們希望自己的墓地擁
[BZOJ1227][SDOI2009]虔誠的墓主人(樹狀陣列+掃描線)
題目: 我是超連結 題解: 首先離散橫縱座標. 以縱座標為第一關鍵字,橫座標為第二關鍵字排序依次考慮每個點. 對於相鄰的兩個點a,b; 如果a.y=b.y;設在這一行,a左邊算上a有sa棵樹,b右邊算上b有sb棵樹. 那麼這一行上a,b之間的點都會
【SDOI2009】bzoj1227 虔誠的墓主人
Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒
bzoj1227 [SDOI2009]虔誠的墓主人(組合公式+離散化+線段樹)
1227: [SDOI2009]虔誠的墓主人 Time Limit: 5 Sec Memory Limit: 259 MB Description 小W 是一片新造公墓的管理人。公墓可以看成一塊N×M 的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地
虔誠的墓主人(BZOJ1227)(洛谷P2154)解題報告
emp 裝飾 楊輝三角 span 記錄 upd 藍色 標簽 for 題目描述 小W是一片新造公墓的管理人。公墓可以看成一塊N×M的矩形,矩形的每個格點,要麽種著一棵常青樹,要麽是一塊還沒有歸屬的墓地。 當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊