Codechef SEAARC Serejaと弧(ブロックの組み合わせ数)

私は実際にそれをするしないでください......

トピックへのリンク:https://www.codechef.com/problems/SEAARC

さて、この質問は、実際のスキルの列挙を検討している......

対象者の要件です\(ABAB \)数は非常に良い、この要求がされていませんが、間隔とで異なる色の総数は\(AABB、ABBA \)より良い需要があります

求めて、変換を補完\(ANS0、ANS1、ANS2を\) 総数、表現\(AABB \)、\ (ABBA \)番号

\(ANS0 \)だけでなく、カウント

\(ANS1 \) 列挙(\ Bの\)左エンドポイント

\(ANS2 \) ブロックを議論

場合\(A、B \)は小さな色(ブロックの色数が閾値未満である)であり、列挙子\(\)は、二次元に、ポイント数をポイントを左右端

場合\(\)がある大きな色\(B \)は少し色、列挙である\(\)の種類、及び次いで列挙\(B \)を入力し、エンドポイントについて、維持することが見出さ式をプッシュプレフィックスと左のポイントを列挙する必要性を排除

場合\(B \)が大きい色で同様に列挙され、(B \)\種、次に列挙する\(\)を入力し、左端、同様の左端点は、列挙を省略しています

昨日の午後から今朝行います。

最適な時間複雑性理論\(O(N \のSQRT { N Nログ\})\)

コード

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<vector>
#include<cmath>
#define llong long long
using namespace std;

const int N = 1e5;
const int P = 1e9+7;
const llong INV2 = 5e8+4;
int nxt[N+3];
int lstpos[N+3];
int a[N+3];
int num[N+3];
int cnum[N+3];
llong tmp0[N+3],tmp1[N+3],tmp2[N+3];
vector<int> clrpos[N+3];
int n,m,B;
llong ans1,ans2a,ans2b,ans2c,ans0,ans;

llong C2(llong x) {return x*(x-1ll)/2ll%P;}
llong update(llong &x,llong y) {x = (x+y)%P;}

struct BITree
{
    llong tr[N+3]; int siz;
    void addval(int lrb,llong val)
    {
        while(lrb<=siz)
        {
            update(tr[lrb],val);
            lrb += (lrb&(-lrb));
        }
    }
    llong querysum(llong rb)
    {
        llong ret = 0ll;
        while(rb)
        {
            update(ret,tr[rb]);
            rb -= (rb&(-rb));
        }
        return ret;
    }
    void clear()
    {
        for(int i=0; i<=siz; i++) tr[i] = 0ll;
    }
} bit1,bit2;

void getans0() //ans0=ËùÓÐÑÕÉ«C(num,2)Á½Á½³Ë»ýÖ®ºÍ ²»ËãAAAA 
{
    llong cur = 0ll;
    for(int i=1; i<=m; i++)
    {
        llong tmp = C2(num[i]);
        update(ans0,cur*tmp%P);
        update(cur,tmp);
    }
}

void getans1() //²»ËãAAAA 
{
    llong tmp = 0ll; //µ±Ç°×ܹ²Í¬É«Çø¼äµÄ¸öÊý 
    for(int i=1; i<=n; i++)
    {
        update(ans1,(tmp-C2(cnum[a[i]]))*(num[a[i]]-cnum[a[i]]-1)); //ÕâÖÖÑÕÉ«×ܸöÊý¼õÕâ֮ǰµÄ¸öÊý-1£¬µÈÓÚÕâÖ®ºóµÄ¸öÊý£¬³ËÒÔÇ°ÃæµÄÒìÉ«¸öÊý 
        update(tmp,(llong)cnum[a[i]]); //ÕâÖÖÑÕɫ֮ǰµÄ¸öÊý 
        cnum[a[i]]++;
    }
}

void getans2a() //small-small ²»ËãAAAA 
{
    bit1.siz = n; bit1.clear(); llong cur = 0ll;
    for(int i=1; i<=n; i++) //ö¾ÙÓҶ˵ã 
    {
        if(num[a[i]]<=B)
        {
            int tnum = 0;
            for(int j=nxt[i]; j; j=nxt[j])
            {
                llong tmp = cur-bit1.querysum(j)-C2(tnum)+P+P; //>jµÄ×ó¶ËµãµÄ¸öÊý=×ܸöÊý¼õ<=jµÄ¸öÊý£¬È¥µôͬɫµÄ¸öÊý(²»ËãiºÍj)
                update(ans2a,tmp);
                tnum++; //ͬɫ¸öÊý 
            }
            for(int j=nxt[i]; j; j=nxt[j]) //ÓÉÓÚÊÇÓҶ˵ãСÓÚj£¬ÏÈÐ޸ĺó²éѯ 
            {
                cur++; //Ä¿Ç°Çø¼ä×ܸöÊý,¼´bit1.querysum(i) 
                bit1.addval(j,1);
            }
        }
    }
}

void getans2b() //large-small
{
    for(int i=1; i<=m; i++) //ö¾ÙAÖÖÀà
    {
        if(num[i]>B) 
        {
            tmp1[0] = 0ll; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);
            for(int j=1; j<=m; j++)  //ö¾ÙBÖÖÀà 
            {
                if(num[j]<=B)
                {
                    llong cur = 0ll;
                    for(int k=0; k<clrpos[j].size(); k++)
                    {
                        int rb = clrpos[j][k];
                        llong tmp = (num[i]-tmp1[rb])*cur%P;
                        update(ans2b,tmp); 
                        update(cur,tmp1[rb]); //lb²»¿ÉµÈÓÚrb, ËùÒÔÏȸüÐÂans2bÔÙ¸üÐÂcur 
                    }
                }
            }
        }
    }
}

void getans2c() //large-large or small-large ²»ËãAAAA 
{
    for(int i=1; i<=m; i++) //ö¾ÙBµÄÖÖÀà 
    {
        if(num[i]>B)
        {
            tmp1[0] = 0; for(int j=1; j<=n; j++) tmp1[j] = tmp1[j-1]+(a[j]==i?1:0);
            for(int j=1; j<=m; j++) //ö¾ÙAµÄÖÖÀà 
            {
                if(i==j) continue;
                llong cur1 = 0ll,cur2 = 0ll;
                for(int k=0; k<clrpos[j].size(); k++) //ö¾Ùra
                {
                    //¸üÐÂans2c 
                    int ra = clrpos[j][k];
                    llong tmp = tmp1[ra]*tmp1[ra]%P*k%P;
                    update(ans2c,tmp);
                    tmp = tmp1[ra]*(-2ll*cur1-k)%P+P;
                    update(ans2c,tmp);
                    tmp = cur2+cur1+P;
                    update(ans2c,tmp);
                    //¸üÐÂcur1,cur2 
                    update(cur2,tmp1[ra]*tmp1[ra]);
                    update(cur1,tmp1[ra]);
                }
            }
        }
    }
    ans2c = ans2c*INV2%P;
}

int main()
{
    scanf("%d",&n); B = sqrt(n)/2;
    for(int i=1; i<=n; i++) scanf("%d",&a[i]),num[a[i]]++,m = max(m,a[i]),clrpos[a[i]].push_back(i);
    for(int i=1; i<=n; i++)
    {
        nxt[i] = lstpos[a[i]];
        lstpos[a[i]] = i;
    }
    getans0();
    getans1();
    getans2a();
    getans2b();
    getans2c();
    ans = ((ans0-ans1-ans2a-ans2b-ans2c)%P+P)%P;
    printf("%lld\n",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/suncongbo/p/11108704.html