zoukankan      html  css  js  c++  java
  • 【bzoj 2038】 [2009国家集训队]小Z的袜子(算法效率--莫队分块算法 模版题)

    题意:小Z有N只袜子,有不同的颜色。他有M个提问,问从编号为[L,R]的袜子中随机选一双同色的袜子的概率,用最简分数表示。

    解法:经典的莫队算法——无修改、不强制在线(可离线)、状态转移可以一步完成。

    步骤如下:
         1.对询问按第一关键字的平方根 sqrt(x) 从小到大排序进行分组,再是各组中按第二关键字 y 从小到大排序。O(m log m)。
         2.一步步转移,第一关键字最多转移 O(sqrt(n)),第二关键字是 O(n) ,相结合就是 O(n*sqrt(n))。
    总时间复杂度就是 O(n*sqrt(n))。

    P.S.我第一个代码WA怎么改都对不了,应该是不能直接对颜色的计数数组通过 +1 和 -1 对答案的贡献不同而直接转移状态。而要减去原来该数对答案的贡献,再加上新的贡献。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<iostream>
     6 #include<cmath>
     7 using namespace std;
     8 typedef long long LL;
     9  
    10 const int N=50010,M=50010,D=50010;
    11 int n,m,sqn;
    12 int c[N],h[N];
    13 LL ans[M][2];
    14 struct query{int l,r,id;}q[M];
    15  
    16 bool cmp(query x,query y)
    17 {
    18     int xx=x.l/sqn,yy=y.l/sqn;
    19     if (xx!=yy) return xx<yy;
    20     return x.r<y.r;
    21 }
    22 int read()
    23 {
    24     char ch=getchar();
    25     int x=0;
    26     while (ch<'0'||ch>'9') ch=getchar();
    27     while (ch>='0'&&ch<='9') x=x*10+ch-'0', ch=getchar();
    28     return x;
    29 }
    30 LL gcd(int x,int y) {return y?gcd(y,x%y):x;}
    31 int main()
    32 {
    33     n=read(),m=read();
    34     for (int i=1;i<=n;i++) c[i]=read();
    35     for (int i=1;i<=m;i++)
    36     {
    37       q[i].l=read(),q[i].r=read();
    38       q[i].id=i;
    39     }
    40     sqn=sqrt(n);
    41     sort(q+1,q+1+m,cmp);
    42      
    43     int l=1,r=1;
    44     LL sum=0;
    45     memset(h,0,sizeof(h));
    46     h[c[1]]++;
    47     for (int i=1;i<=m;i++)
    48     {
    49       while (l<q[i].l) sum=sum-2*h[c[l]]+2,h[c[l]]--,l++;
    50       while (r>q[i].r) sum=sum-2*h[c[r]]+2,h[c[r]]--,r--;
    51       while (l>q[i].l) l--,sum+=2*h[c[l]],h[c[l]]++;
    52       while (r<q[i].r) r++,sum+=2*h[c[r]],h[c[r]]++;
    53       LL w=(q[i].r-q[i].l)*(q[i].r-q[i].l+1);
    54       LL gd=gcd(sum,w);
    55       ans[q[i].id][0]=sum/gd,ans[q[i].id][1]=w/gd;
    56     }
    57     for (int i=1;i<=m;i++)
    58       printf("%I64d/%I64d
    ",ans[i][0],ans[i][1]);
    59     return 0;
    60 }
    WA
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<iostream>
      6 using namespace std;
      7 const int Max=50010;
      8 int n,m,t=0;
      9 int s[Max],c[Max],ans1[Max],ans2[Max];
     10 struct hp{int l,r,t,k;}
     11 a[Max];
     12 int gcd(int x,int y)
     13 {
     14     if (x<y) swap(x,y);
     15     if (x%y==0) return y;
     16     return gcd(y,x%y);
     17 }
     18 int cmp(const void *x,const void *y)
     19 {
     20     hp xx=*(hp *)x;
     21     hp yy=*(hp *)y;
     22     if (xx.t==yy.t) return xx.r-yy.r;
     23     return xx.t-yy.t;
     24 }
     25 int make(int x)
     26 {   //if (x<2) return 0;
     27     if (x%2==0) return (x/2)*(x-1);
     28     return x*((x-1)/2);
     29 }
     30 void block(int id,int l,int r,int ll,int rr)
     31 {
     32     /*if (ll<l)
     33       for (int i=ll;i<l;i++)
     34       {//因为ll为0,所以每次都会make(-1),出现负数便错误!//若特殊算第一次,或算1~n为初始值,才行
     35   //幸亏我想着算组合make时,若x<2宣布了2个怎么办,没有进一步看x=0或1时不会算错,就加了判断语句,便发现对了一些
     36         t-=make(s[c[i]]);
     37         s[c[i]]--;
     38         t+=make(s[c[i]]);
     39       }*/
     40     if (ll<l)
     41       for (int i=ll;i<l;i++)
     42       {
     43         t-=make(s[c[i]]);
     44         s[c[i]]--;
     45         t+=make(s[c[i]]);
     46       }
     47     if (ll>l)
     48       for (int i=l;i<ll;i++)
     49       {
     50         t-=make(s[c[i]]);
     51         s[c[i]]++;
     52         t+=make(s[c[i]]);
     53       }
     54     if (rr<r)
     55       for (int i=rr+1;i<=r;i++) 
     56       {
     57         t-=make(s[c[i]]);
     58         s[c[i]]++;
     59         t+=make(s[c[i]]);
     60       }
     61     if (rr>r)
     62       for (int i=r+1;i<=rr;i++)
     63       {
     64         t-=make(s[c[i]]);
     65         s[c[i]]--;
     66         t+=make(s[c[i]]);
     67       }
     68     int tt,x;
     69     if (!t) {ans1[a[id].k]=0; ans2[a[id].k]=1; return;}
     70     tt=make(r-l+1);//t/tt
     71     x=gcd(tt,t);
     72     ans1[a[id].k]=t/x;
     73     ans2[a[id].k]=tt/x;
     74 }
     75 int main()
     76 {
     77     //freopen("a.in","r",stdin);
     78     //freopen("b.out","w",stdout);
     79     scanf("%d%d",&n,&m);
     80     
     81     for (int i=1;i<=n;i++)
     82       scanf("%d",&c[i]);
     83     double x=sqrt(n);
     84     for (int i=1;i<=m;i++)
     85     {
     86       scanf("%d%d",&a[i].l,&a[i].r);
     87       a[i].t=(int)(a[i].l/x);
     88       a[i].k=i;
     89     }
     90     qsort(a+1,m,sizeof(hp),cmp);
     91     
     92     memset(s,0,sizeof(s));
     93     //a[0].l=0; a[0].r=0;
     94     a[0].l=1;a[0].r=n;
     95     for (int i=1;i<=n;i++) s[c[i]]++;
     96     for (int i=1;i<=n;i++)
     97       t+=make(s[i]);
     98     for (int i=1;i<=m;i++)
     99       block(i,a[i].l,a[i].r,a[i-1].l,a[i-1].r);
    100     for (int i=1;i<=m;i++)
    101       printf("%d/%d
    ",ans1[i],ans2[i]);
    102   //system("pause");
    103     return 0;
    104 }
    AC
  • 相关阅读:
    Python day 34 并发编程、PID/PPID、实现多进程得两种方式
    Python Day33:粘包问题及粘包解决方案
    数据分析
    数据分析
    爬虫 之 mongodb数据库
    爬虫
    爬虫
    爬虫
    flask框架
    flask框架
  • 原文地址:https://www.cnblogs.com/konjak/p/6065030.html
Copyright © 2011-2022 走看看