出题人好评。
评测机差评。

A 救救喵咪

二位偏序。如果数据范围大的话直接树状数组,不过才1000就\(O(n^2)\)暴力就ok了。

#include <bits/stdc++.h>
struct Node {
    int x, y;
}a[1010];
 
int main() {
    int n;
    std::cin >> n;
    for(int i = 1; i <= n; ++i) {
        std::cin >> a[i].x >> a[i].y;
    }
    for(int i = 1; i <= n; ++i) {
        int ans = 0;
        for(int j = 1; j <= n; ++j) {
            if(a[j].x > a[i].x && a[j].y > a[i].y) ++ans;
        }
        printf("%d\n", ans);
    }
}

B 救救兔子

二分经典题。注意初始化即可。

#include <bits/stdc++.h>
 
#define N 100010
#define ll long long
#define int long long
ll a[N];
int m, n;
 
ll find_max(ll x) {
    int l = 1, r = n, ans = n;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(a[mid] >= x) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    return a[ans];
}
 
ll find_min(ll x) {
    int l = 1, r = n, ans = 1;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(a[mid] <= x) l = mid + 1, ans = mid;
        else r = mid - 1;
    }
    return a[ans];
}
 
signed main() {
#ifdef WIN64
    freopen("1.in", "r", stdin);
#endif
    std::cin >> n;
    for(int i = 1; i <= n; ++i) std::cin >> a[i];
    std::sort(a + 1, a + n + 1);
    std::cin >> m;
    while(m--) {
        ll x; std::cin >> x;
        ll t = find_min(x), t1 = find_max(x);
        if(abs(t - x) > abs(t1 - x)) std::swap(t, t1);
        printf("%lld\n", t);
    }
}

C 救救企鹅

和gdoi2017d1t1很像,显然直接跑一遍kmp就行了,就是把输出改为标记,注意因为不能重复覆盖,所以要跳过一整段,注意这个时候中间这段也要更新next值。

#include <bits/stdc++.h>
using namespace std;
 
#define N 1000010
char s[N], a[N], b[N];
int nxt[N], vis[N];
 
int main() {
    scanf("%s%s%s", s + 1, a + 1, b + 1);
    int n = strlen(s + 1);
    int m = strlen(a + 1), k = strlen(b + 1);
    for(int i = 2, j = 0; i <= m; ++i) {
        while(j && a[j + 1] != a[i]) j = nxt[j];
        if(a[j + 1] == a[i]) ++j;
        nxt[i] = j;
    }
    for(int i = 1, j = 0; i <= n; ++i) {
        while(j && a[j + 1] != s[i]) j = nxt[j];
        if(a[j + 1] == s[i]) ++j;
        if(j == m) {
            vis[i - m + 1] = 1;
            int lim = i + m - 2;
            j = 0;
            for(; i <= lim; ++i) {
                while(j && a[j + 1] != s[i]) j = nxt[j];
                if(a[j + 1] == s[i]) ++j;
            }
            --i;
        }
    }
    for(int i = 1; i <= n; ++i) {
        if(vis[i] == 1) {
            i += m - 1;
            for(int l = 1; l <= k; ++l) putchar(b[l]);
            continue;
        }
        putchar(s[i]);
    }
}

D 数糖纸

尺取法经典题。
瓶颈在离散(换成map,set也行)
map会被卡。
牛客评测机差评..一样的代码交一次70交第二次90...
因为被卡了所以就没ak了qaq。

map代码(大概在50~70浮动,加了读优的话在70~90浮动)

#include <bits/stdc++.h>
using namespace std;
  
#define N 1000010
#define ll long long
int n, last[N];
ll a[N];
map<ll, int>v;
  
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%lld", &a[i]);
        if(v[a[i]]) {
            last[i] = v[a[i]];
        }
        v[a[i]] = i;
    }
    int l = 1, ans = 1;
    for(int r = 1; r <= n; ++r) {
        while(l < r && last[r] >= l) ++l;
        ans = max(r - l + 1, ans);
    }
    printf("%d\n", ans);
}

set代码

#include <bits/stdc++.h>
using namespace std;

#define N 1000010
#define ll long long
int n;
int last[N], a[N];
set<int>s;

int main() {
    scanf("%d", &n);
    int l = 1, ans = 0;
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        while(s.count(a[i]) && l < i) s.erase(a[l++]); 
        s.insert(a[i]);
        ans = max(ans, (int)s.size());
    }
    printf("%d\n", ans);    
}