离散化扫描线搞搞。。。好像要个o(1)快速乘什么的。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100500 #define mod 2147483648LL using namespace std; struct pnt { long long x,y; }p[maxn]; long long n,m,w,x,y,k,c[maxn][12],hash[maxn],top=0,t[maxn],cnt[maxn],tmp[maxn]; long long mul(long long a,long long b) { long long d=(long long)floor(a*(long double)b/mod+0.5); long long ret=a*b-d*mod; if (ret<0) ret+=mod; return ret; } bool cmp(pnt x,pnt y) { if (x.y!=y.y) return x.y<y.y; return x.x<y.x; } void get_table() { c[0][0]=1; for (long long i=1;i<=w;i++) { c[i][0]=1; for (long long j=1;j<=min(k,i);j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; } } long long find(long long x) { return lower_bound(hash+1,hash+top+1,x)-hash; } long long lowbit(long long x) { return (x&(-x)); } void modify(long long x,long long val) { for (long long i=x;i<=top;i+=lowbit(i)) t[i]=(t[i]+val)%mod; } long long ask(long long x) { long long ret=0; for (long long i=x;i>=1;i-=lowbit(i)) ret=(ret+t[i])%mod; return ret; } void get_ans() { long long ans=0;long long ret; long long l=1,r=1; while (l<=w) { r=l; while ((p[r+1].y==p[l].y) && (r+1<=w)) r++; ret=r-l+1; for (long long i=l+1;i<=r;i++) ans=(ans+mul(mul(c[i-l][k],c[ret-i+l][k]),(ask(find(p[i].x)-1)-ask(find(p[i-1].x)))%mod)%mod)%mod; for (long long i=l;i<=r;i++) { long long tr=find(p[i].x); tmp[tr]++; long long val=ask(tr)-ask(tr-1); modify(tr,-val);modify(tr,mul(c[tmp[tr]][k],c[cnt[tr]-tmp[tr]][k])); } l=r+1; } printf("%lld\n",ans); } int main() { scanf("%lld%lld",&n,&m); scanf("%lld",&w); for (long long i=1;i<=w;i++) { scanf("%lld%lld",&p[i].x,&p[i].y); hash[++top]=p[i].x; } scanf("%lld",&k); get_table(); sort(hash+1,hash+top+1);top=unique(hash+1,hash+top+1)-hash-1; sort(p+1,p+w+1,cmp); for (long long i=1;i<=w;i++) cnt[find(p[i].x)]++; get_ans(); return 0; }