제출 #676066

#제출 시각아이디문제언어결과실행 시간메모리
676066alexddZoltan (COCI16_zoltan)C++17
0 / 140
638 ms45024 KiB
#pragma GCC optimize("O3,unroll-loops")
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 1000000007;
int n;
int a[200001];
map<int,int> mp;
map<int,int> nor;
int cntn=0;
void normalizare()
{
    for(int i=1;i<=n;i++)
        mp[a[i]]++;
    int val;
    for(auto it:mp)
    {
        val=it.first;
        cntn++;
        nor[val]=cntn;
    }
    for(int i=1;i<=n;i++)
        a[i]=nor[a[i]];
}
struct node
{
    int mxm[2];
    int cnt[2];
};
node combine(node x, node y)
{
    node rez;
    for(int i=0;i<2;i++)
    {
        rez.mxm[i] = max(x.mxm[i],y.mxm[i]);
        rez.cnt[i] = 0;
        if(x.mxm[i]==rez.mxm[i])
            rez.cnt[i] += x.cnt[i];
        if(y.mxm[i]==rez.mxm[i])
            rez.cnt[i] += y.cnt[i];
    }
    rez.cnt[0]%=MOD;
    rez.cnt[1]%=MOD;
    return rez;
}
node aint[810000];
node gol;
void upd(int nod, int st, int dr, int poz, node newval)
{
    if(st==dr)
    {
        aint[nod]=newval;
        return;
    }
    int mij=(st+dr)/2;
    if(poz<=mij)
        upd(nod*2,st,mij,poz,newval);
    else
        upd(nod*2+1,mij+1,dr,poz,newval);
    aint[nod]=combine(aint[nod*2],aint[nod*2+1]);
}
node qry(int nod, int st, int dr, int le, int ri)
{
    if(le>ri)
        return gol;
    if(le==st && ri==dr)
        return aint[nod];
    int mij=(st+dr)/2;
    return combine(qry(nod*2,st,mij,le,min(mij,ri)),
                   qry(nod*2+1,mij+1,dr,max(mij+1,le),ri));
}
int put(int x, int exp)
{
    if(exp==0) return 1;
    if(exp%2==0) return put((x*x)%MOD, exp/2);
    else return (put((x*x)%MOD, exp/2)*x)%MOD;
}
signed main()
{
    gol.mxm[0]=0;
    gol.mxm[1]=0;
    gol.cnt[0]=0;
    gol.cnt[1]=0;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    normalizare();
    node dp;
    node x;
    for(int i=1;i<=n;i++)
    {
        x = qry(1,1,cntn,a[i]+1,cntn);
        dp.mxm[0] = x.mxm[0] + 1;
        dp.cnt[0] = x.cnt[0];
        if(dp.mxm[0]==1)
            dp.cnt[0]=1;

        x = qry(1,1,cntn,1,a[i]-1);
        dp.mxm[1] = max(x.mxm[0], x.mxm[1]) + 1;
        dp.cnt[1]=0;
        if(x.mxm[0] + 1 == dp.mxm[1])
            dp.cnt[1] += x.cnt[0];
        if(x.mxm[1] + 1 == dp.mxm[1])
            dp.cnt[1] += x.cnt[1];

        if(dp.mxm[1]==1)
            dp.cnt[1]=1;
        dp.cnt[1]%=MOD;
        dp.cnt[0]%=MOD;

        upd(1,1,cntn,a[i],dp);
    }
    x = aint[1];
    int maxim=0,cntm=0;
    maxim=max(x.mxm[0],x.mxm[1]);
    if(x.mxm[0]==maxim)
        cntm+=x.cnt[0];
    if(x.mxm[1]==maxim)
        cntm+=x.cnt[1];
    cout<<maxim<<" "<<(cntm*put(2,n-maxim))%MOD;
    return 0;
}
/**

trebuie sa gasesc 2 secvente, una fiind crescatoare si cealalta descrescatoare
cea crescatoare incepe unde se termina cea descrescatoare

dp[i][0] = lungimea maxima a unei secvente descrescatoare care se termina pe pozitia i
dp[i][1] = lungimea maxima a 2 secvente, prima descrescatoare, a 2-a crescatoare, care se termina pe pozitia i

dp[i][0] = max(dp[j][0] + 1), unde a[j] > a[i]
dp[i][1] = max(max(dp[j][1] + 1 cu a[j] < a[i]), max(dp[j][0] + 1 cu a[j] < a[i]))

*/
#Verdict Execution timeMemoryGrader output
Fetching results...