耍了这么久,我又回来了。不知道赶不赶得上
题目传送门
C题不会
LIS多种解法
DP法(n*n)
lower/upper_bound优化(n*logn)
方法精髓 int k = lower_bound( t + 1, t + 1 + b, c[ i ] ) - t ;
A
优化后的模板(lower_bound)
int main() {
int a, b;
cin >> a;
while (a--) {
cin >> b;
for (int i = 1; i <= b; i++) {
cin >> c[i];
t[i] = 999999999;
}
int ans = 1;
for (int i = 1; i <= b; i++) {
int k = lower_bound(t + 1, t + 1 + b, c[i])-t;
ans = max(k, ans);
t[k] = c[i];//更改
}
cout << ans << endl;
}
}
B
本质还是LIS
int main() {
int a;
int b;
int d;
int t = 0;
while (scanf("%d", &a)!=EOF) {
t++;
int ans = 1;
for (int i = 1; i <= a; i++) {
scanf("%d%d", &b, &d);
c[b] = d;
dp[i] = 999999999;
}
for (int i = 1; i <= a; i++) {
int k = upper_bound(dp + 1, dp + 1 + a, c[i]) - dp;
ans = max(k, ans);
dp[k] = c[i];
}
printf("Case %d:\n", t);
if (ans == 1)
printf("My king, at most %d road can be built.\n\n", ans);
else
printf("My king, at most %d roads can be built.\n\n", ans);
//注意输出格式加不加s
}
}
D
模板题,直接写,dp法(n*n)
while (cin >> a&&a) {
for (int i = 1; i <= a; i++)cin >> c[i];
for (int i = 1; i <= a; i++)dp[i] = c[i];
int ans=-999999999;
for (int i = 1; i <= a; i++) {
for (int j = 1; j < i; j++) {
if (c[j] < c[i])
dp[i] = max(dp[i], dp[j] + c[i]);
}
ans = max(ans, dp[i]);
}
cout << ans << endl;
}
E
开个数组记录答案就行了
int main() {
int a, b;
cin >> a;
while (a--) {
cin >> b;
for (int i = 1; i <= b; i++) {
cin >> c[i];
t[i] = 999999999;
}
for (int i = 1; i <= b; i++) {
int k = lower_bound(t + 1, t + 1 + b, c[i])-t;
p[i] = k;
t[k] = c[i];//更改
}
for (int i = 1; i <= b; i++) {
if (i == 1)cout << p[i];
else
cout << " " << p[i];
}
cout << endl;
}
}
F
根据题意,序列最长上升,下降长度要大于等于b-1;
int main() {
int a;
//cin >> a;
scanf("%d", &a);
while (a--) {
int b;
int ans = 1;
int ans2 = 1;
//cin >> b;
scanf("%d", &b);
for (int i = 1; i <= b; i++) {
//cin >> c[i];
scanf("%d", &c[i]);
t[i] = 999999999;
t2[i] = 999999999;
}
//最长上升子序列
for (int i = 1; i <= b; i++) {
int k = upper_bound(t + 1, t + b + 1, c[i])-t;
ans = max(ans, k);
t[k] = c[i];
}
reverse(c + 1, c + b + 1);
//最长下降子序列
for (int i = 1; i <= b; i++) {
int k = upper_bound(t2 + 1, t2 + b + 1, c[i]) - t2;
ans2 = max(ans2, k);
t2[k] = c[i];
}
//cout << ans << " " << ans2 << "?????"<<endl;
if (ans >= b - 1 || ans2 >= b - 1)printf("YES\n");
else printf("NO\n");
}
}
G
思路大魔王,我丢
由题意可以知晓 a [ i ] - a[ j ] >= i - j
移相一下就可以知道
int main() {
int a;
int b;
scanf("%d", &a);
int p = 1;
while (a--) {
printf("Case #%d:\n", p++);
scanf("%d", &b);
for (int i = 1; i <= b; i++) {
scanf("%d", &c[i]);
c[i] -= i;//相当于移相操作
dp[i] = 999999999;
}
int ans = 0;//注意初始化
for (int i = 1; i <= b; i++) {
int k = upper_bound(dp + 1, dp + 1 + b, c[i])-dp;
ans = max(ans, k);
dp[k] = c[i];
}
printf("%d\n", b - ans);
}
}