zoukankan      html  css  js  c++  java
  • Luogu2154 虔诚的墓主人

    Description

    link

    给定平面上 (n) 个点和一个整数 (k)

    求平面上有多少个点满足正上,正下,正左,正右都有 (k) 个点

    如果某一方向上有大于 (k) 个点,那么需要计算选择 (k) 个的方案

    方案数对 (2147483648) 取模

    (nle 10^5 k le 10)

    Solution

    如果你看到原题面,那就加一句,这题要离散化

    这题上来先观察一下,如果满足有大于 (k) 个点,就是个组合计数,乘一下组合数就好了

    这里要注意的是要按照杨辉的方法 (dp) 算组合数,这个模数不是质数,逆元不行

    其实答案就是

    [suminom l k inom r k inom u k inom d k ]

    这里的 (l r u d) 表示的是在点的方位的树的数量

    这是一句废话,但是如果没思考是想不到的

    先把所有的已知点按 (x)(y) 为第一第二关键字排序

    然后我们对于 (x) 值相同的点

    上下的树数可以拿桶来求,已知当前点坐标的左右的也可以用桶

    然后我们发现这里需要求出来区间内 (suminom l k inom r k) 的值

    上树状数组维护一下即可

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	#define mp make_pair
    	#define f first
    	#define s second
     	const int N=5e5+10,mod=2147483648;
    	int n,m,w,k,x[N],y[N],a[N],b[N],tx,ty,ans; 
    	struct BIT{
    		int c[N];
    		inline int lowbit(int x){return x&(-x);}
    		inline int ask(int x){int res=0; for(;x;x-=lowbit(x)) (res+=c[x])%=mod; return res;}
    		inline void add(int x,int d){for(;x<=w;x+=lowbit(x)) (c[x]+=d)%=mod; return ;}
    	}T;
    	int cx[N],cy[N];
    	pair<int,int> p[N];
    	#define C(x,y) cl[x][y]
    	int u,d,l[N],r,cl[N][25];
    	signed main()
    	{
    		n=read(); m=read(); w=read();
    		for(int i=1;i<=w;++i) a[i]=x[i]=read(),b[i]=y[i]=read();
    		k=read(); cl[0][0]=1; 
    		for(int i=1;i<=w;++i) 
    		{
    			cl[i][0]=1; for(int j=1;j<=k;++j) cl[i][j]=(cl[i-1][j]+cl[i-1][j-1])%mod;
    		}
    		sort(a+1,a+w+1); sort(b+1,b+w+1);
    		for(int i=1;i<=w;++i) x[i]=lower_bound(a+1,a+w+1,x[i])-a,++cx[x[i]];
    		for(int i=1;i<=w;++i) y[i]=lower_bound(b+1,b+w+1,y[i])-b,++cy[y[i]];
    		for(int i=1;i<=w;++i) p[i]=mp(x[i],y[i]);
    		sort(p+1,p+w+1); 
    		for(int i=1;i<w;++i)
    		{
    			if(p[i].f==p[i-1].f) d++; else d=1;
    			u=cx[p[i].f]-d; 
    			if(u) 
    			{
    				ans+=cl[d][k]*cl[u][k]%mod*((T.ask(p[i+1].s-1)-T.ask(p[i].s)+mod)%mod)%mod;
    				ans%=mod; 
    			}
    			l[p[i].s]++;
    			int s1=C(l[p[i].s],k)*C(cy[p[i].s]-l[p[i].s],k)%mod;
    			int s2=((T.ask(p[i].s)-T.ask(p[i].s-1))%mod+mod)%mod;
    			T.add(p[i].s,((s1-s2)%mod+mod)%mod);
    		}
    		printf("%lld
    ",(ans%mod+mod)%mod);
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    css基本的东西
    css写一个梯形
    js事件代理
    css的垂直居中
    css的6中居中的方式
    css的小三角实现的方式
    css清楚浮动的几种常用方法
    css中的伪类和伪元素
    js回调
    11.10 chkconfig:管理开机服务
  • 原文地址:https://www.cnblogs.com/yspm/p/12827813.html
Copyright © 2011-2022 走看看