#include<stdio.h>
int main()
{
int N;
scanf("%d",&N);
int queue[N]; //记录每个轨道的最小序号
int queueNum=0; //轨道数量
int num;
for (int i = 0; i < N; i++)
{
scanf("%d", &num);
if (i == 0 || num > queue[queueNum]) {
//新数大于所有轨道中的最小序号时,添加新轨道。
//在维护过程中,最后加入的轨道永远存在着当前最大的序号,所以将新数与最后加入的轨道比较就行
queue[++queueNum] = num;
}
else
{ //新数小于最后加入的轨道中的序号时,将其插入与其差值最小的子串中去
//使用顺序查找时有测试点超时,所以这里用二分来找
int l=0;int r=queueNum;int mid;
while(l<=r)
{
mid=(l+r)/2;
if(queue[mid]>num)r=mid-1;
else l=mid+1;
}
queue[l]=num;
}
}
printf("%d",queueNum);
}
#include <iostream>
using namespace std;
int fcode[501];//父节点集
int road[5001][2];
int flag[501];
void resum(int n) {
//初始化
for (int i = 0; i < n; i++) {
fcode[i] = i;
};
}
int findf(int a) {
int f = a;
while (f != fcode[f]) {
f = fcode[f];
};
//压缩路径
while (fcode[a] != f) {
int x = fcode[a];//记录a的直属下一节点
fcode[a] = f;//将a的下一节点改为根节点
a = x;//准备下一轮压缩
};
return f;
}
int bcj(int n, int m) {
for (int i = 0; i < m; i++) {
if (!flag[road[i][0]] || !flag[road[i][1]]) {
continue;
};
int fa = findf(road[i][0]);
int fb = findf(road[i][1]);
fcode[fb] = fa;
};
int sum = 0;
//压缩一遍
for (int i = 0; i < n; i++) {
findf(i);
};
for (int i = 0; i < n; i++) {
if (!flag[i]) {
continue;
};
if (fcode[i] == i) {
sum++;
};
};
return sum;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
flag[i] = 1;
};
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d%d", &a, &b);
road[i][0] = a;
road[i][1] = b;
};
resum(n);
int rsum = bcj(n, m);
int num, sum;
scanf("%d", &num);
for (int i = 0; i < num; i++) {
if (i != 0) {
printf("\n");
};
int code;
scanf("%d", &code);
resum(n);
flag[code] = 0;
sum = bcj(n, m);
if (sum > rsum) {
printf("Red Alert: City ");
printf("%d", code);
printf(" is lost!");
}
else {
printf("City ");
printf("%d", code);
printf(" is lost.");
};
rsum = sum;
};
if (rsum == 0) {
printf("\n");
printf("Game Over.");
};
}