Codeforces Round #656 (Div.3) 部分題解
阿新 • • 發佈:2020-08-23
Codeforces Round #656 (Div. 3)
A. Three Pairwise Maximums
思路
分類討論,x、y、z三個數有兩個數相等且另一個數小於等於這兩個數就能找到合法的a、b、c,具體直接看程式碼吧。(水題練下python)
T=int(input()) for i in range(T): x,y,z=map(int,input().split()) if x==y: if z>x: print("NO") continue else: print("YES") print(x,z,1) elif x==z: if y>x: print("NO") continue else: print("YES") print(y,x,1) elif y==z: if x>y: print("NO") continue else: print("YES") print(1,x,z) else:print("NO")
B. Restore the Permutation by Merger
思路
簡單貪心,每次碰到不同的數直接輸出或者記錄下來最後輸出都ok。
T=int(input()) for tt in range(T): hh=[] vis=[0]*200 ans=[] n=int(input()) hh=list(map(int,input().split())) for i in hh: if vis[i]==0: ans.append(i) vis[i]=1 for i in ans: print(i,end=' ')
C. Make It Good
思路
因為只能刪字首,所以很容易想到從後往前找一個倒序先增後減序列,碰到“谷”直接記錄序號退出迴圈輸出就好了。
#include<bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; int a[200050]; // inline int read() // { // int x=0,f=1;char ch=getchar(); // while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} // while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} // return x*f; // } int main() { //freopen(".in","r",stdin); //freopen(".out","w",stdout); IO; int t;cin>>t; while(t--) { int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; int f=0,ans=0; for(int i=n-1;i>=1;i--) { if(!f) { if(a[i]<a[i+1])f=1; } else { if(a[i]>a[i+1]){ans=i;break;} } } cout<<ans<<"\n"; } return 0; }
D. a-Good String
思路
讀完題發現很明顯的分治,n是2的17次方,寫個遞迴暴力就能過。
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
char s[132000];
// inline int read()
// {
// int x=0,f=1;char ch=getchar();
// while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
// while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
// return x*f;
// }
int solve(int l,int r,char ch)
{
if(l==r)return s[l]!=ch;
int mid=l+r>>1;
int cntl=0,cntr=0;
for(int i=l;i<=mid;i++)if(s[i]!=ch)cntl++;
for(int i=mid+1;i<=r;i++)if(s[i]!=ch)cntr++;
int ans1=solve(mid+1,r,ch+1),ans2=solve(l,mid,ch+1);
return min(ans1+cntl,ans2+cntr);
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
int n;cin>>n;
cin>>s+1;
cout<<solve(1,n,'a')<<'\n';
}
return 0;
}
E. Directing Edges
思路
感覺是道好題,有向無向邊需要分開處理,拓撲排序來避免環的出現也很妙。首先對所有的有向邊建圖判環,有環直接輸出NO,無環則剩下的邊可以按照拓撲序從小到大連邊,拓撲序就按編號從小到大連邊。根據拓撲排序的原理,一個點在訪問過後不會再被訪問,可以完美避免環的出現。
此處有參考suxxsfe的題解,傳送門。
#include<bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=2e5+50;
int Head[maxn],V[maxn*2],Nxt[maxn*2],du[maxn],vis[maxn],crcl[maxn],step[maxn];
int tot,cnt,cntt,cnttt;
int n,m;
pair<int,int>e[maxn],ee[maxn];
void Add(int u,int v){V[++tot]=v;Nxt[tot]=Head[u];Head[u]=tot;}
int dfs(int u)
{
vis[u]=crcl[u]=1;
for(int i=Head[u];i;i=Nxt[i])
{
int v=V[i];
if(crcl[v])return 1;
if(!vis[v])
{
int tmp=dfs(v);
if(tmp)return 1;
}
}
crcl[u]=0;
return 0;
}
void topsort(){
queue<int>p,q;
int i,u,v;
for(i=1;i<=n;i++)if(!du[i])q.push(i);
while(!q.empty()){
cnt++;
while(!q.empty())
{
u=q.front();q.pop();
step[u]=cnt;
for(i=Head[u];i;i=Nxt[i])
{
v=V[i];
du[v]--;
if(!du[v])p.push(v);
}
}
swap(p,q);
}
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
IO;
int t;cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int type,u,v;
cin>>type>>u>>v;
if(type)
{
Add(u,v);du[v]++;
ee[++cnttt].first=u;ee[cnttt].second=v;
}
else e[++cntt].first=u,e[cntt].second=v;
}
int f=0;
for(int i=1;i<=n;i++)
if(!vis[i])
{
int tmp=dfs(i);
if(tmp){f=1;break;}
}
if(f){cout<<"NO\n";}
else
{
topsort();
cout<<"YES\n";
for(int i=1;i<=cnttt;i++)
cout<<ee[i].first<<" "<<ee[i].second<<"\n";
for(int i=1;i<=cntt;i++)
if(step[e[i].first]<step[e[i].second]||(step[e[i].first]==step[e[i].second]&&e[i].first<e[i].second))cout<<e[i].first<<" "<<e[i].second<<"\n";
else cout<<e[i].second<<" "<<e[i].first<<"\n";
}
for(int i=1;i<=n;i++)Head[i]=vis[i]=crcl[i]=du[i]=0;
tot=cnt=cntt=cnttt=0;
}
return 0;
}
F. Removing Leaves
思路
明天補
G. Columns Swaps
思路
明天補