zoukankan      html  css  js  c++  java
  • 【Foreign】异色弧 [树状数组]

      异色弧

    Time Limit: 20 Sec  Memory Limit: 256 MB

    Description

      

    Input

      

    Output

      仅一行一个整数表示答案。

    Sample Input

      8
      1 2 3 1 2 3 2 1

    Sample Output

      8

    HINT

      

    Main idea

      给定若干个点,每个点有一个颜色,颜色一样的可以组成一个区间,询问有几个交。

    Solution

      BearChild只会70分的做法,记录N表示区间个数,效率为O(Nlog(N))。这里介绍一下。

      我们基于将所有区间提取出来计算,可以用一个vector存一下记录相同颜色的,然后相同颜色的任意组合即可组成可行的区间。

      首先我们考虑容斥颜色不同的相交个数 = 不考虑颜色的总相交个数 - 颜色相同的相交个数。然后我们分段来解:

      1. 不考虑颜色的总相交个数:
        我们考虑带log的算法,先将所有区间按照右端点(细节:若相同则将左端点大的放在前面,保证不会算入答案)排序,然后顺序往后做,每次用树状数组在区间左端点+1区间(右端点-1)处-1(细节:右端点-1处是为了处理前一个的右端点=这一个的左端点情况),然后每次只要查询(左端点-1)的前缀和,显然就是在这个区间前和这个区间的交的个数。这样我们就可以计算出总相交个数了。

      2.颜色相同的相交个数:
        我们考虑如何计算颜色相同的相交个数,设a表示一个颜色的个数,显然个数就是:C(a,4)。也就是任意4个相同颜色点可以组成一个交。

      然后我们相减一下,就可以得到答案啦。注意一下细节。

    Code

      1 #include<iostream>  
      2 #include<algorithm>  
      3 #include<cstdio>  
      4 #include<cstring>  
      5 #include<cstdlib>  
      6 #include<cmath>  
      7 #include<vector>
      8 using namespace std;
      9 
     10 typedef long long s64;
     11 const int ONE = 100010;
     12 const int MOD = 1e9+7;
     13 
     14 vector <int> q[ONE];
     15 
     16 int n;
     17 int A[ONE];
     18 int cnt,Ans;
     19 int Max,vis[ONE];
     20 int Jc[ONE],inv[ONE];
     21 
     22 struct power
     23 {
     24         int l,r;
     25 }a[20000001];
     26 
     27 bool cmp(const power &a,const power &b)
     28 {
     29         if(a.r == b.r) return a.l > b.l;
     30         return a.r < b.r;
     31 }
     32 
     33 void Moit(int &a)
     34 {
     35         if(a<MOD) a+=MOD;
     36         if(a>MOD) a-=MOD;
     37 }
     38 
     39 int get()
     40 { 
     41         int res=1,Q=1;    char c;
     42         while( (c=getchar())<48 || c>57)
     43         if(c=='-')Q=-1;
     44         if(Q) res=c-48; 
     45         while((c=getchar())>=48 && c<=57) 
     46         res=res*10+c-48; 
     47         return res*Q; 
     48 }
     49 
     50 namespace D
     51 {
     52         int Quickpow(int a,int b)
     53         {
     54             int res=1;
     55             while(b)
     56             {
     57                 if(b&1) res=(s64)res*a%MOD;
     58                 a=(s64)a*a%MOD;
     59                 b>>=1;
     60             }
     61             return res;
     62         }
     63     
     64         void Deal_Jc(int k)
     65         {
     66             Jc[0]=1;
     67             for(int i=1;i<=k;i++) Jc[i] = (s64)Jc[i-1]*i%MOD;
     68         }
     69         
     70         void Deal_inv(int k)
     71         {
     72             inv[0]=1;    inv[k] = Quickpow(Jc[k],MOD-2);
     73             for(int i=k-1;i>=1;i--) inv[i] = (s64)inv[i+1]*(i+1)%MOD;
     74         }
     75         
     76         void pre(int k)
     77         {
     78             Deal_Jc(k);    Deal_inv(k);
     79         }
     80 }
     81 
     82 int C(int n,int m)
     83 {
     84         if(n < m) return 0;
     85         return (s64)Jc[n]*inv[m]%MOD*inv[n-m]%MOD; 
     86 }
     87 
     88 namespace Bit
     89 {
     90         int C[ONE];
     91         
     92         int lowbit(int x)
     93         {
     94             return x&-x;
     95         }
     96     
     97         void Add(int R,int x)
     98         {
     99             for(int i=R;i<=n;i+=lowbit(i))
    100                 C[i]+=x, Moit(C[i]);
    101         }
    102         
    103         int Query(int R)
    104         {
    105             int res=0;
    106             for(int i=R;i>=1;i-=lowbit(i))
    107                 res+=C[i], Moit(res);
    108             return res;
    109         }
    110 }
    111 
    112 int main()
    113 {      
    114         n=get();    D::pre(n+1);
    115         for(int i=1;i<=n;i++)
    116         {
    117             A[i]=get();
    118             q[A[i]].push_back(i);
    119             Max=max(Max,A[i]); 
    120         }
    121         for(int k=1;k<=Max;k++)
    122         {
    123             if(!q[k].size()) continue;
    124             Ans-=C(q[k].size(),4);    Moit(Ans);
    125             for(int i=0;i< q[k].size();i++)
    126             for(int j=i+1;j< q[k].size();j++)
    127                 a[++cnt].l=q[k][i], a[cnt].r=q[k][j];
    128         }
    129         
    130         sort(a+1,a+cnt+1,cmp);
    131         for(int i=1;i<=cnt;i++)
    132         {
    133             Ans += Bit::Query(a[i].l-1);
    134             Moit(Ans);
    135             Bit::Add(a[i].l,1), Bit::Add(a[i].r-1,-1);
    136         }
    137         
    138         printf("%d",Ans); 
    139 }
    View Code
  • 相关阅读:
    HDU_2047——EOF字符串排序排列问题,递推
    HDU_2046——骨牌铺放问题,递推
    HDU_2045——RPG问题,递推
    HDU_2044——蜜蜂走蜂房,递推
    HDU_2043——判断密码是否安全
    HDU_2042——递归反推
    单例模式
    抽象工厂模式
    工厂方法模式
    C#调用C++DLL传递结构体数组的终极解决方案
  • 原文地址:https://www.cnblogs.com/BearChild/p/6522789.html
Copyright © 2011-2022 走看看