zoukankan      html  css  js  c++  java
  • bzoj2038: [2009国家集训队]小Z的袜子(hose)

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2038

    思路:首先对于一个[l,r]的询问,设col[i]表示第i种颜色在这一区间内的个数,那么随机抽到相同一对的概率就是

    ∑C(col[i],2)/C(r-l+1,2)

    然后有:∑(col[i]^2-col[i])/((r-l+1)*(r-l))

    然后我们发现得到了[l,r]的答案后,我们可以O(1)地得到[l,r-1]和[l,r+1]和[l-1,r]和[l+1,r]的答案。

    这样我们就可以用莫队算法了。

    我们只要按一定顺序去计算答案,就可以得到较优的复杂度。

    求出最小曼哈顿距离生成树,在沿着树边一个一个得到答案即可。

    但是这很复杂....

    于是就有了对l分块,先把询问排序,第一关键字是l所在的块,第二关键字是r的大小,按照排序后的顺序计算就可以使复杂度变为O(n^1.5)

    (我怎么感觉这充满了暴力...)

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=50010;
    using namespace std;
    typedef long long ll;
    int n,m,col[maxn],sz,pos[maxn],k;ll ans,s[maxn];
    struct que{int l,r,id;ll a,b;}a[maxn];
    ll sqr(ll a){return a*a;}
    void update(int x,int add){ans-=sqr(s[col[x]]),s[col[x]]+=add,ans+=sqr(s[col[x]]);}
    
    bool cmp1(que a,que b){ 
    	if (pos[a.l]==pos[b.l]) return a.r<b.r; 
    	return a.l<b.l; 
    }
    bool cmp2(que a,que b){return a.id<b.id;}
    
    void work(){
    	sort(a+1,a+1+m,cmp1);
        for (int i=1,l=1,r=0;i<=m;i++){
    		for (;r<a[i].r;r++) update(r+1,1);
    		for (;r>a[i].r;r--) update(r, -1);
    		for (;l<a[i].l;l++) update(l, -1);
    		for (;l>a[i].l;l--) update(l-1,1);
    		if (a[i].l==a[i].r){a[i].a=1;continue;}
    		a[i].a=ans;
    	}
    	sort(a+1,a+1+m,cmp2);
    	for (int i=1;i<=m;i++) printf("%lld
    ",a[i].a);
    }
      
    int main(){
    	scanf("%d%d%d",&n,&m,&k);sz=(int)sqrt(n);
    	for (int i=1;i<=n;i++) scanf("%d",&col[i]);
    	for (int i=1;i<=n;i++) pos[i]=(i-1)/sz+1;
    	for (int i=1;i<=m;i++) scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i;
    	work();
    	return 0; 
    } 



  • 相关阅读:
    在Django中如何使用Redis
    Redis的基本操作
    短信接口的频率限制
    版本控制器git
    windows生成公私钥以及应用
    luffy前台组件的搭建
    周末大作业
    同源策略的解决方案
    全局Response对象和全局异常捕获和日志
    爬虫之代理池搭建
  • 原文地址:https://www.cnblogs.com/thythy/p/5493544.html
Copyright © 2011-2022 走看看