zoukankan      html  css  js  c++  java
  • Luogu P1494 [国家集训队]小Z的袜子

    比较简单的莫队题,主要是为了熟练板子。

    先考虑固定区间时我们怎么计算,假设区间([l,r])内颜色为(i)的袜子有(cnt_i)只,那么对于颜色(i)来说,凑齐一双的情况个数为:

    • (cnt_i=0)时,贡献为(0),这个我们特别处理(显然吧)
    • (cnt_i>0)时,贡献为(cnt_icdot (cnt_i-1)) (先挑出一只再挑另一只)

    最后我们考虑所有颜色以及总情况数,那么此时凑出一双概率为:

    [frac{sum cnt_icdot(cnt_i-1)}{(r-l+1)cdot(r-l-2)} ]

    首先还是考虑如何快速地转移区间,假设我们已经求出了([l,r])的贡献(即上式的分母部分)(ans),那么我们考虑:

    • 推出([l-1,r],[l,r+1])。假设此时加入的袜子颜色为(i),那么(ans=ans-cnt_icdot(cnt_i-1)+cnt_icdot(cnt_i+1))
    • 推出([l+1,r],[l,r-1])。假设此时加入的袜子颜色为(i),那么(ans=ans-cnt_icdot(cnt_i-1)+(cnt_i-2)cdot(cnt_i-1))

    然后就可以(O(1))转移啦,剩下的就是莫队基本操作了

    CODE

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=50005;
    struct data
    {
    	int l,r,id;
    	long long ans1,ans2;
    }q[N];
    int n,m,L,R,a[N],cnt[N],blk[N],size;
    long long res;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch; while (!isdigit(ch=tc()));
    	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
    }
    inline void write(long long x)
    {
    	if (x>9) write(x/10);
    	putchar(x%10+'0');
    }
    inline bool cmp1(data a,data b)
    {
    	if (blk[a.l]==blk[b.l]) return blk[a.l]&1?a.r<b.r:a.r>b.r;
    	return blk[a.l]<blk[b.l];
    }
    inline bool cmp2(data a,data b)
    {
    	return a.id<b.id;
    }
    inline void add(int col)
    {
    	if (++cnt[col]>=2) res+=1LL*cnt[col]*(cnt[col]-1)-1LL*(cnt[col]-1)*(cnt[col]-2);
    }
    inline void del(int col)
    {
    	if (--cnt[col]>=1) res+=1LL*cnt[col]*(cnt[col]-1)-1LL*cnt[col]*(cnt[col]+1);
    }
    inline long long gcd(long long n,long long m)
    {
    	return m?gcd(m,n%m):n;
    }
    inline void divnum(long long a,long long b)
    {
    	if (!a) { puts("0/1"); return; }
    	long long d=gcd(a,b); a/=d; b/=d;
    	write(a); putchar('/'); write(b); putchar('
    ');
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i; read(n); read(m); size=sqrt(n);
    	for (i=1;i<=n;++i) read(a[i]),blk[i]=(i-1)/size+1;
    	for (i=1;i<=m;++i) read(q[i].l),read(q[i].r),q[i].id=i;
    	sort(q+1,q+m+1,cmp1); L=q[1].l; R=q[1].r;
    	for (i=L;i<=R;++i) add(a[i]); q[1].ans1=res; q[1].ans2=1LL*(R-L+1)*(R-L);
    	for (i=2;i<=m;++i)
    	{
    		while (L<q[i].l) del(a[L++]); while (L>q[i].l) add(a[--L]);
    		while (R>q[i].r) del(a[R--]); while (R<q[i].r) add(a[++R]);
    		q[i].ans1=res; q[i].ans2=1LL*(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
    	}
    	for (sort(q+1,q+m+1,cmp2),i=1;i<=m;++i) divnum(q[i].ans1,q[i].ans2);
    	return 0;
    }
    
  • 相关阅读:
    java 正则 二次转义
    HDU1789 Doing Homework again 【贪心】
    扣丁学堂笔记第22天多媒体播放
    [Python]BeautifulSoup—HTML解析包
    Android高级控件(三)——&#160;使用Google ZXing实现二维码的扫描和生成相关功能体系
    Business Process and SAP ERP
    HTML基础知识总结一
    控制器View是怎样创建的?
    cocos2d-x 3.0 场景切换特效汇总
    LeetCode 3Sum
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9541584.html
Copyright © 2011-2022 走看看