제출 #719733

#제출 시각아이디문제언어결과실행 시간메모리
719733lamCopy and Paste 3 (JOI22_copypaste3)C++14
100 / 100
2758 ms168308 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int base = 103LL;
const int mod = 1e9 + 7;
int n,a,b,c;
string s;
const int maxn = 2510;
int pre[maxn][maxn],nnext[maxn][maxn],dp[maxn][maxn];
struct fen_tree2
{
    int f[maxn][maxn];
    void reset(int rt, int sz)
    {
        fill_n(f[rt],sz+1,1e18);
    }
    void update(int rt, int x, int val)
    {
        while (x>0)
        {
            f[rt][x]=min(f[rt][x],val);
            x-=(x&-x);
        }
    }
    int get(int rt, int sz, int x)
    {
        int temp=1e18;
        while (x<=sz)
        {
            temp=min(temp,f[rt][x]);
            x+=(x&-x);
        }
        return temp;
    }
};
fen_tree2 dp2;

map<int,int> mp;

struct fen_tree3
{
    int f[maxn][maxn];
    void reset(int rt, int sz)
    {
        fill_n(f[rt],sz+1,1e18);
    }
    void update(int rt, int sz, int x, int val)
    {
        while (x<=sz)
        {
            f[rt][x]=min(f[rt][x],val);
            x+=(x&-x);
        }
    }
    int get(int rt, int x)
    {
        int temp=1e18;
        while (x>0)
        {
            temp=min(temp,f[rt][x]);
            x-=(x&-x);
        }
        return temp;
    }
};
fen_tree3 dp3;

int h[maxn],p[maxn];
inline int get(int l, int r)
{
    return (h[r]-(h[l-1]*p[r-l+1]%mod)+mod)%mod;
}
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cin>>n;
    cin>>s;
    cin>>a>>b>>c;
    p[0]=1LL;
    for (int i=1; i<=n; i++) p[i]=p[i-1]*base%mod;
    h[0]=0LL;
    for (int i=1; i<=n; i++) h[i]=(h[i-1]*base%mod + (s[i-1]-'a'+1))%mod;
    for (int i=1; i<=n; i++)
        for (int j=i; j<=n; j++) dp[i][j] = a*(j-i+1);
    for (int i=1; i<=n; i++)
    {
        dp2.reset(i,i);
        dp3.reset(i,n-i+1);
    }
    for (int len=1; len<n; len++)
    {
        mp.clear();
        for (int i=1; i+len-1<=n; i++)
        {
            if (i>len) mp[get(i-len,i-1)] = i-len;
            int j=i+len-1;
            if (!mp.count(get(i,j))) pre[i][j]=-1;
            else pre[i][j]=mp[get(i,j)];
        }
        mp.clear();
        for (int j=n; j>=len; j--)
        {
            int i=j-len+1;
            if (n-j>=len) mp[get(j+1,j+len)] = j+len;
            if (!mp.count(get(i,j))) nnext[i][j]=-1;
            else nnext[i][j]=mp[get(i,j)];
        }
    }
    for (int len=1; len<n; len++)
        for (int j=len; j<=n; j++)
    {
        int i=j-len+1;
        int val = min(dp[i][j],min(dp2.get(j,j,i)-i*a,dp3.get(i,j-i+1)+j*a));
//        cerr<<i<<' '<<j<<" := "<<val<<endl;
        int num = 1;
        int last = i-1;
        int x=i; int y=j;
        while (pre[x][y]!=-1)
        {
            int z = pre[x][y];
//            cerr<<last<<' '<<j<<endl;
            dp2.update(j,last,val+b+num*c+(j+1-(num*len))*a);
            last=z;
            num++;
            x=z; y=z+len-1;
        }
        dp2.update(j,last,val+b+num*c+(j+1-(num*len))*a);
        dp2.update(j,i-1,val+i*a);
//        cerr<<":>"<<endl;
//        for (int z=i-1; z>=1; z--)
//        {
//            if (r-z+1>=len)
//            {
//                if (get(z,z+len-1) == get(i,j))
//                {
//                    num++;
//                    r=z-1;
//                }
//            }
//            dp[z][j]=min(dp[z][j],dp[i][j]+b+num*c+(j-z+1-(num*len))*a);
//            dp[z][j]=min(dp[z][j],dp[i][j]+(i-z)*a);
//        }
        num=1;
        last=j+1;
        x=i; y=j;
        while (nnext[x][y]!=-1)
        {
            int z=nnext[x][y];
            dp3.update(i,n-i+1,last-i+1,val+b+num*c+(-i+1-(num*len))*a);
            last=z;
            num++;
            x=z-len+1; y=z;
        }
//        cerr<<i<<' '<<last<<' '<<num<<endl;
        dp3.update(i,n-i+1,last-i+1,val+b+num*c+(-i+1-(num*len))*a);
        dp3.update(i,n-i+1,2,val+(-j)*a);
//        cerr<<":>"<<endl;
//        int l=j+1;
//        for (int z=j+1; z<=n; z++)
//        {
//            if (z-l+1>=len)
//            {
//                if (get(z-len+1,z) == get(i,j))
//                {
//                    num++;
//                    l=z+1;
//                }
//            }
//            dp[i][z]=min(dp[i][z],dp[i][j]+b+num*c+(z-i+1-(num*len))*a);
//            dp[i][z]=min(dp[i][z],dp[i][j]+(z-j)*a);
//        }
//        cout<<i<<' '<<j<<" := "<<dp[i][j]<<'\n';
    }
    int ans = min(dp[1][n],min(dp2.get(n,n,1)-1*a,dp3.get(1,n)+n*a));
    cout<<ans<<'\n';

}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...