[USACO 2020.1 Platinum][LOJ3247]Non-Decreasing Subsequences(CDQ分治)

题面

https://loj.ac/problem/3247

题解

考虑CDQ分治。对于\(solve(l,r,v)\)(其中l,r表示当前处理到的区间的左右端点,v是一个vector,存放当前区间内待处理的所有询问的序号):

  • \(m=(l+r)>>1\)

  • 预处理出\(f[i][j](1{\leq}i{\leq}k,l{\leq}j{\leq}r)\),其中\(f[i][j]=\)

    \[\begin{cases} {以j为左端点,右端点{\leq}m,且a[右端点]=i的不下降子序列数}(l{\leq}j{\leq}m) \\ {以j为右端点,左端点{>m,且a[左端点]=i的不下降子序列数(m<j{\leq}r)}} \end{cases}\]

    对于\(m<j{\leq}r\)来言,有递推式

    \[f[i][j]={\sum\limits_{m<k<j,a[k]{\leq}a[j]}}f[i][k]+[a[j]=i]\],这一过程可以用树状数组优化,从而在\(O((r-l+1)klogk)\)时间内完成预处理。

    另外,需要将空字符串统计进去,就是把\(f[1][m],f[k][m+1]\)都加1。

    接下来,对\(f\)进行前缀和,就可以得到\(f[i][j]=\)

    \[\begin{cases} {l{\leq}左端点,右端点{\leq}m,且a[右端点]=i的不下降子序列数}(l{\leq}j{\leq}m) \\ {j{\geq}右端点,左端点{>m,且a[左端点]=i的不下降子序列数(m<j{\leq}r)}} \end{cases}\]

  • 遍历所有序号\(id{\in}v\)。如果\(R[id]{\leq}m\),将其加入数组vl。如果\(L[id]>m\),将其加入数组vr。

  • 对于其余id,统计答案:

    \[{\sum\limits_{i=1}^{k}}f[i][L[id]]{\sum\limits_{j=i}^{k}}f[j][R[id]]\]。这一过程可以先计算前缀和来优化。

  • 然后递归处理\(solve(l,m,vl),solve(m+1,r,vr)\)

依此过程,solve中预处理的总复杂度是\(O(nklognlogk)\),统计答案的总复杂度是\(O(qk)\)

代码

#include<bits/stdc++.h>

using namespace std;

#define N 50000
#define Q 200000
#define ll long long
#define mod 1000000007
#define rg register
 
namespace ModCalc{
    inline void Inc(ll &x,ll y){
        x += y;if(x >= mod)x -= mod;
    }
    
    inline void Dec(ll &x,ll y){
        x -= y;if(x < 0)x += mod;
    }
    
    inline ll Add(ll x,ll y){
        Inc(x,y);return x;
    }
    
    inline ll Sub(ll x,ll y){
        Dec(x,y);return x;
    }
}
using namespace ModCalc;
 
inline ll read(){
    ll s = 0,ww = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')ww = -1;ch = getchar();}
    while('0' <= ch && ch <= '9'){s = 10 * s + ch - '0';ch = getchar();}
    return s * ww;
}

inline void write(ll x){
    if(x < 0)putchar('-'),x = -x;
    if(x > 9)write(x / 10);
    putchar('0' + x % 10);
}

ll n,q,k;
ll f[20+5][N+5],a[N+5],L[Q+5],R[Q+5];
ll ans[Q+5];
ll s[20+5];

struct BIT{
    ll b[20+5];
    
    inline ll lowbit(ll x){
        return x & -x;
    }
    
    inline void reset(){
        memset(b,0,sizeof(b));
    }
    
    inline void ud(ll x,ll dx){
        for(rg ll i = x;i <= k;i += lowbit(i))Inc(b[i],dx);
    }
    
    inline ll query(ll x){
        ll rt = 0;
        for(rg ll i = x;i;i -= lowbit(i))Inc(rt,b[i]);  
        return rt;
    }
}B;

inline void solve(ll l,ll r,vector<ll>v){
    if(l == r){
        for(rg ll i = 0;i < v.size();i++)ans[v[i]] = 2;
        return;
    }
    ll m = (l + r) >> 1;
    for(rg ll st = 1;st <= k;st++){
        B.reset();      
        for(rg ll i = m + 1;i <= r;i++){
            f[st][i] = B.query(a[i]);
            if(a[i] == st)Inc(f[st][i],1);
            B.ud(a[i],f[st][i]); 
        }
        for(rg ll i = m + 2;i <= r;i++)Inc(f[st][i],f[st][i-1]);
    }
    for(rg ll st = 1;st <= k;st++){
        B.reset();
        for(rg ll i = m;i >= l;i--){
            f[st][i] = B.query(k + 1 - a[i]);
            if(a[i] == st)Inc(f[st][i],1);
            B.ud(k + 1 - a[i],f[st][i]);
        }
        for(rg ll i = m - 1;i >= l;i--)Inc(f[st][i],f[st][i+1]);
    }
    for(rg ll i = l;i <= m;i++)Inc(f[1][i],1); //左半部分为空子串
    for(rg ll i = m + 1;i <= r;i++)Inc(f[k][i],1); //右半部分为空子串 
    vector<ll>vl,vr;
    vl.resize(0);
    vr.resize(0);
    for(rg ll i = 0;i < v.size();i++){
        ll id = v[i];
        if(R[id] <= m)vl.push_back(id);
        else if(L[id] > m)vr.push_back(id);
        else{
            for(rg ll j = k;j >= 1;j--)s[j] = Add(s[j+1],f[j][R[id]]);
            for(rg ll j = 1;j <= k;j++)Inc(ans[id],f[j][L[id]] * s[j] % mod);
        }
    }
    if(vl.size())solve(l,m,vl);
    if(vr.size())solve(m+1,r,vr); 
}

vector<ll>v;

int main(){
    n = read(),k = read();
    for(rg ll i = 1;i <= n;i++)a[i] = read();
    q = read();
    for(rg ll i = 1;i <= q;i++)L[i] = read(),R[i] = read();
    v.resize(0);
    for(rg ll i = 1;i <= q;i++)v.push_back(i);
    solve(1,n,v);
    for(rg ll i = 1;i <= q;i++)write(ans[i]),putchar('\n'); 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xh092113/p/12283379.html
今日推荐