P2344 [USACO11FEB] Generic Cow Protests G

纯粹的發表於2024-04-13

原題連結

題解

1.觀察資料法:看到 \(1e^5\) 想到線性遞推,想到遍歷每頭奶牛試著在它們後面新增隔斷時的分組方案數
2.對於奶牛 \(i\) 它的狀態轉移方程為 \(dp[i]+=dp[j];j<i;sum[j]<=sum[i]\)
3.上述可以把 \(sum\) 看成 x軸, \(dp\) 看成 \(f(x)\),這樣就變成了求小於 \(sum[i]\) 的所有 \(dp[i]\) 的區間求和,而對 \(sum[i]\) 上的 \(dp[i]\) 修改又是單點修改,所以考慮樹狀陣列
4.由於有負數,所以要離散化,注意開頭的零也要離散化進去

code

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
const ll mod=1e9+9;
using namespace std;
ll dp[100005]={0};
ll tree[100005]={0};
ll haxi[100005]={0};
ll n;
ll pre[100005]={0},pre_sort[100005]={0};
ll len=0;

ll query(ll x)
{
    ll sum=0;
    while(x)
    {
        sum+=tree[x];
        sum%=mod;
        x-=lowbit(x);
    }
    return sum;
}

void update(ll x,ll val)
{
    while(x<=len)
    {
        tree[x]+=val;
        tree[x]%=mod;
        x+=lowbit(x);
    }
}

int main()
{
    cin>>n;
    for(ll i=1;i<=n;i++)
    {
        cin>>pre[i];
        pre[i]+=pre[i-1];
        pre_sort[i]=pre[i];
    }

    sort(pre_sort,pre_sort+1+n);

    len=unique(pre_sort,pre_sort+1+n)-pre_sort;//離散化操作,由於前面的隔斷可以選零點後面,所以零點也算上隔斷
    for(int i=0;i<=n;i++) haxi[i]=lower_bound(pre_sort,pre_sort+len,pre[i])-pre_sort+1;//離散化,+1代表第幾小

    update(haxi[0],1);
    for(ll i=1;i<=n;i++)
    {
        dp[i]=query(haxi[i]);
        update(haxi[i],dp[i]);
    }

    //for(int i=1;i<=n;i++) printf("dp:%d\n",dp[i]);
    cout<<dp[n];
    return 0;
}

//對於每個i,求所有滿足presj<presi的dp[j]和,把pres看成下標x,dp看成f(x),則變成求pres-f(x)
//實際上我們只需要直到pres的相對大小即可,所以把他們離散化

相關文章