天梯賽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;
}