牛客OI周赛7-普及组 解题报告
出题人好评。
评测机差评。
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代码(大概在5070浮动,加了读优的话在7090浮动)
#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);
}