天梯赛2
7-10 红色警报
这道题的题意要注意是删去一个城市后增加了多少个区域,而不是有多少个城市变成了单独的点,赛时理解错了题意,用set做会有点有问题。其实很简单,就是bfs搜一下有多少个联通块,每次删除把被删的点打个标记,每次联通块的个数和上一次的比较一下,只要增加就是改变了连通性,这样判断可以规避掉一开始就只有一个点单独是一个联通块的情况。
点击查看代码
void solve() {
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
int ans;
memset(vis,0,sizeof(vis));
ans=0;
for(int j=0;j<n;j++){
if(vis[j]==1)
continue;
vis[j]=1;
q.push(j);
while(!q.empty()){
auto x=q.front();
q.pop();
for(auto e:g[x]){
if(vis[e])
continue;
vis[e]=1;
q.push(e);
}
}
ans++;
}
//cout<<ans<<endl;
int k;
cin>>k;
int ans1;
for(int i=1;i<=k;i++){
int d;
cin>>d;
f[d]=1;
memset(vis,0,sizeof(vis));
ans1=0;
for(int j=0;j<n;j++){
if(vis[j])
continue;
if(f[j])
continue;
vis[j]=1;
q.push(j);
while(!q.empty()){
auto x=q.front();
q.pop();
for(auto e:g[x]){
if(vis[e])
continue;
if(f[e])
continue;
vis[e]=1;
q.push(e);
}
}
ans1++;
}
//cout<<ans1<<endl;
if(ans1>ans){
cout<<"Red Alert: City "<<d<<" is lost!\n";
}
else{
cout<<"City "<<d<<" is lost.\n";
}
ans=ans1;
}
if(k==n){
cout<<"Game Over.\n";
}
return ;
}
7-15 特殊堆栈
这道题就是对顶堆,题意要中间的那个值,那就左右各开一个multiset,我只要保证左边的数量最多比右边多一个,要不就相等,那此时左边的最后一个数就是结果。要注意multiset的语法规则,erase函数删除某个数的话是把所有的都删了,应该先用find函数找到它的位置再删,erase函数也不能删去rbegin要用end的prev
点击查看代码
void tz(){
int x1,x2;
x1=s1.size(),x2=s2.size();
if (x2 - x1 > 0) {
int e = *(s2.begin());
s2.erase(s2.begin());
s1.insert(e);
}
if (x1 - x2 > 1) {
int e = *(s1.rbegin());
s1.erase(prev(s1.end()));
s2.insert(e);
}
return ;
}
void solve() {
int n;
cin>>n;
for(int i=1;i<=n;i++){
string s;
cin>>s;
if(s=="Push"){
int x;
cin>>x;
q.push(x);
if(s1.empty()){
s1.insert(x);
}
else {
if (x >= *(s1.rbegin())) {
s2.insert(x);
}
else {
s1.insert(x);
}
}
tz();
}
else if(s=="Pop"){
if(q.empty()){
cout<<"Invalid\n";
continue;
}
int x=q.top();
q.pop();
cout<<x<<endl;
//cout<<s1.size()<<" "<<s2.size()<<endl;
//int e=*(s1.rbegin());
auto ee=s1.find(x);
if(ee!=s1.end()){
s1.erase(ee);
}
else{
s2.erase(s2.find(x));
}
tz();
}
else{
if(q.empty()){
cout<<"Invalid\n";
continue;
}
cout<<*(s1.rbegin())<<endl;
}
}
return ;
}
天梯赛3
7-7 连续因子
这道题其实就是暴力,因为要找连续因子,那不就是暴力循环起点,然后暴力向后循环,要注意第一维只要找到sqrt(n)就可以了,但是第二维不行,不过第二维最多12个,也无所谓。要注意本身是素数的情况。那就是全跑完了都没找到因子。
点击查看代码
void solve() {
int n;
cin>>n;
int dans=0;
int max1=0,l,d;
for(int i=2;i*i<=n;i++){
int x=n;
int ans=0;
if(x%i==0){
ans++;
x/=i;
for(int j=i+1;j<=n;j++){
if(x%j==0){
ans++;
x/=j;
}
else{
break;
}
}
if(ans>max1){
max1=ans;
//dans=1;
l=i;
}
// else if(ans==max1){
// //dans++;
// }
}
}
if(max1==0){
cout<<1<<endl;
cout<<n<<endl;
return ;
}
cout<<max1<<endl;
for(int i=l;i<=l+max1-1;i++){
cout<<i;
if(i!=l+max1-1){
cout<<"*";
}
else{
cout<<"\n";
}
}
return ;
}
7-9 哈利波特的考试
这道题一眼弗洛伊德,但怎么会有人把板子敲错啊。。。
就是纯板子题,不放代码了。
7-11 病毒溯源
这道题我一看题面感觉很像并查集,因为保证了每个病毒都是由唯一的病毒变异而来,我就想着从每一个点开始去找祖先,看看谁最长,但是这个做法很暴力,直接运行超时,其实反过来想,这就是个树啊,找最长链,那就是找到树的根节点,然后计算每一个节点的深度。
点击查看代码
void dfs(int x){
if(dp[x]>max1){
max1=dp[x];
dd=x;
}
for(auto e:g[x]){
dp[e]=dp[x]+1;
dfs(e);
}
}
void solve() {
int n;
cin>>n;
for (int i = 0;i < n;i++){
fa[i] = i;
}
for(int i=0;i<n;i++){
int k;
cin>>k;
for(int j=1;j<=k;j++){
int x;
cin>>x;
g[i].push_back(x);
fa[x]=i;
}
sort(g[i].begin(),g[i].end());
}
int d;
for(int i=0;i<n;i++){
if(fa[i]==i){
d=i;
break;
}
}
dp[d]=1;
dfs(d);
//cout<<d<<" "<<dd<<endl;
vector<int>ve;
while(1){
if(dd==fa[dd])
break;
ve.push_back(dd);
dd=fa[dd];
}
ve.push_back(d);
int x=ve.size();
cout<<x<<endl;
for(int i=x-1;i>=0;i--){
cout<<ve[i];
if(i!=0){
cout<<" ";
}
else{
cout<<endl;
}
}
return;
}