【SDOI2009】bzoj1227 虔誠的墓主人
阿新 • • 發佈:2019-01-06
Description
小W 是一片新造公墓的管理人。公墓可以看成一塊N×M
的矩形,矩形的每個格點,要麼種著一棵常青樹,要麼是一塊還沒有歸屬的墓地。當地的居民都是非常虔誠的基督徒,他們願意提前為自己找一塊合適墓地。為了體現自己對主的真誠,他們希望自己的墓地擁有著較高的虔誠度。一塊墓地的虔誠度是指以這塊墓地為中心的十字架的數目。一個十字架可以看成中間是墓地,墓地的正上、正下、正左、正右都有恰好k
棵常青樹。小W 希望知道他所管理的這片公墓中所有墓地的虔誠度總和是多少 Input第一行包含兩個用空格分隔的正整數N 和M,表示公墓的寬和長,因此這個矩形公墓共有(N+1) ×(M+1)個格點,左下角的座標為(0,
0),右上角的座標為(N, M)。第二行包含一個正整數W,表示公墓中常青樹的個數。第三行起共W
行,每行包含兩個用空格分隔的非負整數xi和yi,表示一棵常青樹的座標。輸入保證沒有兩棵常青樹擁有相同的座標。最後一行包含一個正整數k,意義如題目所示。
Output包含一個非負整數,表示這片公墓中所有墓地的虔誠度總和。為了方便起見,答案對2,147,483,648 取模。
顯然可以離散化,然後列舉每個墓地就可以做到
改變列舉的方法,列舉左右相鄰的兩棵樹,計算他們之間的墓地的方案數。如果暴力求和還是
按照行掃描,維護當前行每個位置上方和下方的樹的個數,就可以用樹狀陣列維護某一段區間的答案和。這樣就做到了
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> a[100010];
int n,m,k,mx,my,
tx[100010],ty[100010],ordx[100010],ordy[100010],
s[200010],downc[100010],upc[100010],
c[100010][15];
void add(int p,int x)
{
for (int k=p;k<=my;k+=k&-k) s[k]+=x;
}
int qry(int l,int r)
{
int ret=0;
for (int k=r-1;k;k-=k&-k) ret+=s[k];
for (int k=l;k;k-=k&-k) ret-=s[k];
return ret;
}
int main()
{
/*freopen("in.txt","r",stdin);*/
int x,y,ans=0;
scanf("%*d%*d%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&tx[i],&ty[i]);
ordx[i]=tx[i];
ordy[i]=ty[i];
}
scanf("%d",&k);
for (int i=0;i<=n;i++) c[i][0]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=i&&j<=k;j++)
c[i][j]=c[i-1][j]+c[i-1][j-1];
sort(ordx+1,ordx+n+1);
sort(ordy+1,ordy+n+1);
mx=unique(ordx+1,ordx+n+1)-ordx-1;
my=unique(ordy+1,ordy+n+1)-ordy-1;
for (int i=1;i<=n;i++)
{
x=lower_bound(ordx+1,ordx+mx+1,tx[i])-ordx;
y=lower_bound(ordy+1,ordy+my+1,ty[i])-ordy;
a[x].push_back(y);
}
for (int i=1;i<=mx;i++)
for (int j=0;j<a[i].size();j++)
downc[a[i][j]]++;
for (int i=1;i<=mx;i++)
{
sort(a[i].begin(),a[i].end());
for (int j=0;j<a[i].size();j++)
{
y=a[i][j];
add(y,c[upc[y]][k]*(-c[downc[y]][k]+c[downc[y]-1][k]));
downc[y]--;
}
for (int j=0;j<a[i].size()-1;j++)
ans+=c[j+1][k]*c[a[i].size()-j-1][k]*qry(a[i][j],a[i][j+1]);
for (int j=0;j<a[i].size();j++)
{
y=a[i][j];
add(y,c[downc[y]][k]*(-c[upc[y]][k]+c[upc[y]+1][k]));
upc[y]++;
}
}
printf("%d\n",ans&2147483647);
}