三倍经验题!惊喜不惊喜?
BZOJ
洛谷
Codevs ←欲知为何WA请戳这个!!!
我想大家一定都会 O(nm) O ( n m ) 的做法吧,就是暴力扫整个地图??
那只需要做一个简单的离散化就可以把复杂度优化到 O(w2) O ( w 2 ) 。
然而可能你可能会发现你还是只拿了暴力分
设第i个点上方、下方、左方、右方的常青树个数为 ui,di,li,ri u i , d i , l i , r i ,可以知道
#include
#include
#include
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=100010;
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
struct data{
int x,y;
bool operator < (const data &t)const
{
if(y==t.y) return xreturn yint n,m,w,k,tmp,cnt,ans,x[maxn],y[maxn],h[maxn],l[maxn],t[maxn];
int num[maxn],c[maxn][11];
void add(int pos,int val){for(;pos<=w;pos+=lowbit(pos)) t[pos]+=val;}
int query(int pos)
{
int res=0;
for(;pos;pos-=lowbit(pos)) res+=t[pos];
return res;
}
void input()
{
read(n);read(m);read(w);
for(int i=1;i<=w;i++)
read(p[i].x),read(p[i].y),p[i].x++,p[i].y++,x[i]=p[i].x,y[i]=p[i].y;
read(k);
sort(x+1,x+w+1);sort(y+1,y+w+1);
for(int i=1;i<=w;i++)
{
p[i].x=lower_bound(x+1,x+w+1,p[i].x)-x;
p[i].y=lower_bound(y+1,y+w+1,p[i].y)-y;
l[p[i].x]++;h[p[i].y]++;
}
sort(p+1,p+w+1);
}
void init()
{
c[0][0]=1;
for(int i=1;i<=w;i++)
for(int j=0;j<=10&&j<=i;j++)
c[i][j]=(j?c[i-1][j-1]:0)+c[i-1][j];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
input();
init();
for(int i=1;i<=w;i++)
{
if(i^1&&p[i].y==p[i-1].y)//the same row
{
cnt++;
tmp=query(p[i].x-1)-query(p[i-1].x);
ans+=tmp*(c[cnt][k]*c[h[p[i].y]-cnt][k]);
}
else cnt=0;
num[p[i].x]++;
tmp=c[num[p[i].x]][k]*c[l[p[i].x]-num[p[i].x]][k];
tmp-=c[num[p[i].x]-1][k]*c[l[p[i].x]-num[p[i].x]+1][k];
add(p[i].x,tmp);
}
printf("%d\n",ans&2147483647);
return 0;
}