社区讨论

求卡常/卡空间

P14212[ROI 2016 Day2] 二进制输入参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@miegkk5s
此快照首次捕获于
2025/11/25 18:54
3 个月前
此快照最后确认于
2025/11/25 19:45
3 个月前
查看原帖
CPP
# include <bits/stdc++.h>
# include <bits/extc++.h>
# define rep(i, a, b) for(int i = (a);i <= (b);i ++)
# define urep(i, a, b) for(unsigned int i = (a);i <= (b);i ++)
# define lop(i, a, b) for(int i = (a);i <  (b);i ++)
# define dwn(i, a, b) for(int i = (a);i >= (b);i --)
# define int64 long long
# define ___main signed main()
# define f64 double
# define f32 float
# define f128 long double
# define int128 __int128
# define i128 ((__int128)1)
# define ret return
# define inl inline
# define reg register
# define fn void
# define elif else if
# define pb push_back
# define pp pop_back
using std::cout;
using std::cin;
# define CASES() int T;cin >> T;while(T--)
# define FaILurEg(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
# define N 300005
# define mod  100000000000000009
# define modd 100000000000000007
# define B 1024
# define uint unsigned int
int n, m, L, c[N];
std::string M, s[N];
inline int min(int a, int b){return a>b?b:a;}
inline int max(int a, int b){return a<b?b:a;}
constexpr int __B[] = {8, 16, 32, 64, 96,128,256,512,768,1024,1280,1536,1792,2048,2304,2560,2816,3072,3328,3584,3840,4096,4352,4608,4864,5120,5376,5632,5888,6144,6400,6656,6912,7168,7424,7680,7936,8192,8448,8704,8960,9216,9472,9728,9984,10240,10496,10752,11008,11264,11520,11776,12032,12288,12544,12800,13056,13312,13568,13824,14080,14336,14592,14848};
template<typename X>
struct wekter {
   size_t siz;X *mem;signed x = -1;
   inline void push_back(X a) {
      if(mem == nullptr) 
         mem = (X*)std::malloc((sizeof(X)) * __B[++ x]);
      if(siz == __B[x]) 
         mem = (X*)std::realloc(mem,sizeof(X) *__B[++ x]);
      mem[siz ++] = a;
   }
   inline size_t size(){return siz;}
   inline X* begin(){return mem;}
   inline X* end(){return mem + siz;}
};
struct custom_hash {
    inline static int64_t splitmix64(int64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    inline size_t operator()(int64_t x) const {
        static const int64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

namespace smallStr {// for all pref/suf use hashmap
   std::vector<int> Str;
   __gnu_pbds::gp_hash_table<int64, int, custom_hash> G;
   //int G[19373934], GG[19491002];
   void Build() {
      for(auto i : Str) {int64 H0 = 0, H1 = 0;
         //std::cerr << "STRING " << i << " ";
         rep(j, 0, s[i].size() - 1)
            H0 = H0 * 13 + s[i][j] - '/',H0 %= mod,
            G[H0] = ((!G[H0])?c[i]:min(c[i],G[H0]));
         H0 = 0;int64 P = 1, PP = 1;H1 = 0;
         dwn(j, s[i].size() - 1, 0) 
            H0 = H0 + (s[i][j] - '/') * P,H0 %= mod,
            G[H0] = ((!G[H0])?c[i]:min(c[i],G[H0])), 
            P = P * 13 % mod;
         //assert(G.size() <= 600000);
      }
   }
}
namespace bigStr {
   std::vector<int> Str;
   wekter<std::pair<int, int> > Add[N], Qry[N];
   int Z[N * 2];
   void countZ_pref() {
      // assert(Str.size() <= 0);
      std::string S$;
      for(auto I : Str) {
         S$ = s[I] + '$' + M;
         Z[0] = 0;
         int l = 0, r = 0;
         rep(i, 1, S$.size() - 1) {
            if(i <= r && Z[i - l] < r - i + 1) Z[i] = Z[i - l];
            else {
               Z[i] = max(0, r - i + 1);
               while(i + Z[i] < S$.size() && S$[Z[i]] == S$[i + Z[i]]) 
                  Z[i] ++;
               if(i + Z[i] - 1 > r) l = i, r = i + Z[i] - 1;
            }
            if(i > s[I].size() && (Z[i]))
               Add[i - s[I].size()].push_back({I, i - s[I].size() + Z[i] - 1}); 
         }
      }
   }
   void countZ_suf() {
      std::string S$;
      for(auto I : Str) {
         S$ = M + '$' + s[I];
         std::reverse(S$.begin(), S$.end());
         Z[0] = 0;
         int l = 0, r = 0;
         rep(i, 1, S$.size() - 1) {
            if(i <= r && Z[i - l] < r - i + 1) Z[i] = Z[i - l];
            else {
               Z[i] = max(0, r - i + 1);
               while(i + Z[i] < S$.size() && S$[Z[i]] == S$[i + Z[i]]) 
                  Z[i] ++;
               if(i + Z[i] - 1 > r) l = i, r = i + Z[i] - 1;
            }
            if(i > s[I].size() && (Z[i]))
               Qry[m - (i - s[I].size()) + 1].push_back({I, m - (i - s[I].size()) + 1 - Z[i] + 1});
         }
      }
   }
}
int64 dp[N], st[N][20];
int64 Heap[N + 600], Hp[N];
___main {
//FaILurEg("P14212");
   std::ios::sync_with_stdio(0);cin.tie(0);
   cin >> m >> n >> L;cin >> M;
   rep(i, 1, n) cin >> c[i] >> s[i];
   urep(i, 1, B * (m /B + 1)) Heap[i] = 0x3f3f3f3f3f3f3f3f, Hp[i / B] = 0x3f3f3f3f3f3f3f3f;
   rep(i, 1, n) if(s[i].size() < B) smallStr::Str.push_back(i);
                else bigStr::Str.push_back(i);
   smallStr::Build();
   bigStr::countZ_pref();bigStr::countZ_suf();
   rep(i, 1, m) {
      dp[i] = 0x3f3f3f3f3f3f3f3f;
      // if(dp[i] <= 300000000)
      //    std::cerr << i << "xxx\n";
      // smalls
      int64 H = 0, P = 1, HH = 0, PP = 1;
      dwn(j, i - 1, max(0, i - B))
         H = H + (M[j] - '/') * P, H %= mod, P *= 13, P %= mod,
         (smallStr::G.find(H)!=smallStr::G.end())?dp[i] = std::min(dp[j] + smallStr::G[H], dp[i]):91;
      
      //if(dp[i] <= 300000000)
         //std::cerr << dp[i] << "xx\n";
         //std::cout << dp[i] << " \n";
      for(auto [I, R] : bigStr::Add[i])
         Heap[R] = std::min(Heap[R], dp[i - 1] + c[I]),
         Hp[R / B] = std::min(Hp[R / B], Heap[R]);
      int64 Q = 0x3f3f3f3f3f3f3f3f;
      dwn(j, m / B, i / B + 1)
         Q = std::min(Q, Hp[j]);
      dwn(j, (i / B + 1) * B - 1, i)
         Q = std::min(Q, Heap[j]);
      dp[i] = std::min(Q, dp[i]); 
      for(auto [I, L] : bigStr::Qry[i]) {
         // min [L,i]
         //assert(L >= 1);
         int len = i - L + 1, j = std::__lg(len);
         //assert(L - 1 + (1 << j) - 1 >= 0);
         //assert(L + (1 << j) >= 2);
         //assert(L - 1 + (1 << j) - 1 < i);
         int64 T = std::min(st[i - 1][j], st[L - 1 + (1 << j) - 1][j]);
         dp[i] = std::min(dp[i], T + c[I]);
      } 
      // if(dp[i] <= 300000000)
      //    std::cerr << i << "!\n";
      st[i][0] = dp[i];
      for(int j = 1;i - (1 << j) + 1 >= 0;j ++)
         st[i][j] = std::min(st[i][j - 1], st[i - (1 << (j- 1))][j - 1]);
      // if(dp[i] <= 300000000)
      //    std::cerr << i << "?\n";
   }
   cout << (dp[m]<0x3f3f3f3f3f3f3f3f?dp[m]:-1) << "\n";
   ret 0;}
根号分治,小块哈希,大块用Z函数处理前后缀转化为dp方程,mle求条。

回复

0 条回复,欢迎继续交流。

正在加载回复...