2022年多校冲刺NOIP联训测试5

又双叒叕垫底,

A 旅行日记

判断一下即可?注意一下细节

code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int x = 0; char c = getchar();
    while(c > '9' || c < '0')c = getchar();
    do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c >= '0' && c <= '9');
    return x;
}
const int maxn = 100005;
int d[maxn], h[maxn], n, m, mx;
int main(){
    n = read(); m = read();
    for(int i = 1; i <= m; ++i)d[i] = read(), h[i] = read();
    mx = d[1] + h[1] - 1;
    for(int i = 2; i <= m; ++i){
        int dt = d[i] - d[i - 1];
        int dh = h[i] - h[i - 1];
        if(dh < 0) dh = -dh;
        if(dh > dt){printf("IMPOSSIBLE\n");return 0;}
        mx = max(mx, max(h[i], h[i - 1]) + (dt - dh) / 2);
    }
    mx = max(mx, h[m] + n - d[m]);
    printf("%d\n",mx);
    return 0;
}

B 运动

单调队列+双指针

\(ST\)表会\(MLE\)可恶。。

code
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 5000005, INF = 0x3f3f3f3f;
int n, a[maxn], k;
int q1[maxn],h1,t1;
int q2[maxn],h2,t2;
int main(){
    scanf("%d%d",&k,&n);
    for(int i = 1; i <= n; ++i)scanf("%d",&a[i]);
    int ans = 1, r = 1; h1 = h2 = 1; a[0] = a[1];
    for(int l = 1; l <= n; ++l){
        while(q1[h1]<l && h1 <= t1)++h1; while(q2[h2]<l && h2 <= t2)++h2;
        while(r <= n){
            ll mx = -INF, mi = INF;
            if(h1 <= t1)mx = a[q1[h1]];mx = max(mx,(ll)a[r]);
            if(h2 <= t2)mi = a[q2[h2]];mi = min(mi,(ll)a[r]);
            if(mx - mi > k)break;
            while(h1 <= t1 && a[q1[t1]] < a[r])--t1; q1[++t1] = r;
            while(h2 <= t2 && a[q2[t2]] > a[r])--t2; q2[++t2] = r;
            ++r;
        }
        ans = max(ans, r - l);
    }
    printf("%d\n",ans);
    return 0;
}

C 回文

\(g[i][j]\)表示\(i - j\)是否为回文

\(ans[l][r]\)表示答案

直接\(DP\)即可

代码用了一点奇怪的预处理,但是好像是对的

code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int x = 0; char c = getchar();
    while(c > '9' || c < '0')c = getchar();
    do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c >= '0' && c <= '9');
    return x;
}
const int maxn = 5005;
char s[maxn];
int n, ans[maxn][maxn],g[maxn][maxn];
int main(){
    scanf("%s",s + 1);
    n = strlen(s + 1);
    for(int i = 1; i <= n; ++i)g[i][i] = g[i][i - 1] = 1;
    for(int i = 2; i <= n; ++i)
      for(int j = 1; j <= n - i + 1; ++j)
        g[j][j + i - 1] = (g[j + 1][i + j - 2] && (s[j] == s[i + j - 1]));
    for(int i = 1; i <= n; ++i)
      for(int j = 1; j + i - 1 <= n; ++j)
        ans[j][i + j - 1] = ans[j + 1][i + j - 1] + ans[j][i + j - 2] - ans[j + 1][i + j - 2] + g[j][i + j - 1];
    int T = read();
    for(int i = 1; i <= T; ++i){
        int l = read(), r = read();
        printf("%d\n",ans[l][r]);
    }
    return 0;
}

基因进化

我还没进化,,,,

upd 进化了

尽量使一侧的字典序尽可能小,前面确定后,其实是后面的串正着接在后面或者反着接在前面

通过二分 + \(hash\)求出\(lcp\)后判断两种哪个字典序较小,对不能翻转的串到后面能翻转处再处理

过程中正串维护正\(hash\),反串维护反\(hash\),保证复杂度

code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<deque>
using namespace std;
#define int long long
const int maxn = 300005;
const int mod = 998244353;
const int base = 1e9  + 7;
inline int read(){
    int x = 0; char c = getchar();
    while(c > '9' || c < '0')c = getchar();
    do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c >= '0' && c <= '9');
    return x;
}
int qpow(int x, int y){
    int ans = 1;
    for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1)ans = 1ll * ans * x % mod;
    return ans;
}
int s[maxn], n ,m, ans[maxn];
int base_pow[maxn], base_inv[maxn];
bool vis[maxn];
void pre(){
    base_pow[0] = 1;
    for(int i = 1; i < maxn; ++i)base_pow[i] = 1ll * base_pow[i - 1] * base % mod;
    base_inv[0] = 1, base_inv[1] = qpow(base, mod - 2);
    for(int i = 2; i < maxn; ++i)base_inv[i] = 1ll * base_inv[i - 1] * base_inv[1] % mod;
}
struct arr{
    int a[maxn], b[maxn], h1[maxn], h2[maxn], la, lb, lla, llb;
    void pre(){
        for(int i = 1; i <= lla; ++i)a[i] = 0;
        for(int i = 1; i <= lla; ++i)h1[i] = 0;
        for(int i = 1; i <= llb; ++i)b[i] = 0;
        for(int i = 1; i <= llb; ++i)h2[i] = 0;
        la = lb = lla = llb = 0;
    }
    void add(int x){
        a[++lla] = x; b[++llb] = x;
        h1[lla] = (1ll * h1[lla - 1] * base + a[lla]) % mod;
        h2[llb] = (1ll * base_pow[llb - 1] * b[llb] + h2[llb - 1]) % mod;
    }
    int get_hasha(int l, int r){if(l > r)return 0;else return (1ll * h1[r] - h1[l - 1] * base_pow[r - l + 1] % mod + mod ) % mod;}
    int get_hashb(int l, int r){if(l > r)return 0;else return ((0ll + h2[r] - h2[l - 1] + mod) % mod * 1ll * base_inv[l - 1]) % mod;}
    int get_hash(int pos, int len){
        if(len <= pos)return get_hashb(pos - len + 1,pos);
        return (1ll * get_hashb(1, pos) * base_pow[len - pos] % mod + get_hasha(1, len - pos)) % mod;
    }
    bool check(int len){
        return get_hash(lb, len) == get_hash(llb, len);
    }
    int get(int pos,int len){
        if(len <= pos)return b[pos - len + 1];
        return a[len - pos];
    }
    void judge(int len){
        int lcp, l = 0, r = len;
        while(l <= r){
            int mid = (l + r) >> 1;
            if(check(mid))lcp = mid, l = mid + 1;
            else r = mid - 1;
        }
        
        if(lcp == n || get(lb, lcp + 1) < get(llb, lcp + 1)){llb = lb; la = lla;}
        else {lla = la; lb = llb;}
    }
    void print(){
        int p = 0;
        for(int i = lb; i; --i)ans[++p] = b[i];
        for(int i = 1; i <= la; ++i)ans[++p] = a[i];
    }
}a;

void solve(){
    a.pre();
    for(int i = 1; i <= n; ++i){
        a.add(s[i]);
        if(!vis[i])a.judge(i);
    }
    a.la = a.lla;
    a.print();
}
void work(){
    n = read(), m = read();
    for(int i = 1; i <= n; ++i)s[i] = read();
    for(int i = 1; i <= m; ++i)vis[read()] = 1;
    solve();
    int ot = 0, ns = 1;
    for(int i = 1; i <= n; ++i){
        ot = (ot + 1ll * ans[i] * ns % mod) % mod;
        ns = 1ll * ns  * 37 % mod;
    }
    printf("%lld\n",ot);
    for(int i = 1; i <= n; ++i)vis[i] = 0;
}
signed main(){
    pre(); int op = read();
    for(int i = 1; i <= op; ++i)work();
    return 0;
}
posted @ 2022-07-25 22:06  Chen_jr  阅读(62)  评论(2编辑  收藏  举报