- A. Three Pairwise Maximums
简单题,但是我想了蛮久的,我哭了。对于满足条件的x,y,z绝对有两个数是相等的而且还要大于另外一个数,我也不好解释为什么,所以,,,,将就一下吧,自己看看样例想想吧,面向答案编程我太难了。
我不是很想写题意,因为本来就是容易理解的英文题,而且出去打比赛都是英文题,大家要习惯看英文
void sove()
{
int a[4];
scanf("%d%d%d",&a[1],&a[2],&a[3]);
sort(a+1,a+1+3);
if(a[3]==a[2]&&a[3]>=a[1])
{
printf("YES\n");
printf("%d %d %d\n",a[1],a[1],a[3]);
}
else
{
printf("NO\n");
}
}
2.B. Restore the Permutation by Merger
这才是签到题该有的样子,题意就不说了,很好理解做法就是从左到右标记数,如果没出现过就输出,并且标记,出现过就直接跳过
void sove()
{
int n;
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
{
scanf("%d",&a[i]);
}
ms(vis,0);
for(int i=1;i<=2*n;i++)
{
if(!vis[a[i]])
{
printf("%d ",a[i]);
vis[a[i]]=1;
}
}
printf("\n");
}
3.C. Make It Good
c题就别人都是模拟过的,我特么用了二分才过,气死我了,这个题肯定满足二分,因为删的越多数,那么越可能是对的,删的越少越不可能是对的。
bool check(int x)
{
int l=x+1,r=n,ma=0;
bool flage=true;
while(r>=l)
{
if(a[l]>=a[r]&&ma<=a[r])
{
ma=a[r];
r--;
}
else if(a[l]<a[r]&&a[l]>=ma)
{
ma=a[l];
l++;
}
else
{
flage=false;
break;
}
}
return flage;
}
void sove()
{
//int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int l=0,r=n-1,ans;
while(r>=l)
{
int mid=(l+r)>>1;
if(check(mid))
{
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
printf("%d\n",ans);
}
4.D. a-Good String
这个题暴力bfs就可以过,没啥好说的,代码里写点东西应该就知道了
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 2e5 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e8;
const double pi=3.141592653589;
char s[maxn],dp[30];
int dfs(int l,int r,char ch)
{
//if(dp[num])return dp[num];
if(l==r)特判一下l==r不然会死循环
{
return ch==s[l]?0:1;
}
int cnt1=0,ans=0,cnt2=0;
for(int i=l;i<=(l+r)/2;i++)
{
if(ch!=s[i])//表示前面一半与ch是否匹配,不匹配就让cnt1++,cnt1表示需要操作的次数
{
cnt1++;
}
}
for(int i=(l+r)/2+1;i<=r;i++)
{
if(ch!=s[i])//表示后面一半与ch是否匹配,
{
cnt2++;
}
}
return min(dfs(l,(l+r)/2,ch+1)+cnt2,dfs((l+r)/2+1,r,ch+1)+cnt1);//注意cnt1与cnt2的位置啊ch+1,列如ch='b',那么ch+1='c'
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
ms(dp,0);
cin>>n>>s+1;
printf("%d\n",dfs(1,n,'a'));
}
return 0;
}
E. Directing Edges
昨天打完比赛才看拓扑排序,今天看别人题解就是用拓扑排序,真的就这么巧吗????
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 2e5 + 50;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e8;
const double pi=3.141592653589;
vector<int>ve[maxn];
int in[maxn],n,pxun[maxn];
bool toop_sort()//拓扑排序板子
{
queue<int>q;
for(int i=1;i<=n;i++)
{
if(!in[i])
{
q.push(i);
}
}
int ans=0;
while(!q.empty())
{
int u=q.front();
q.pop();
pxun[u]=ans++;//记录拓扑序
for(int i=0;i<ve[u].size();i++)
{
int v=ve[u][i];
in[v]--;
if(!in[v])
{
q.push(v);
}
}
}
return ans==n;
}
int vis[maxn],din[maxn],dout[maxn];
void sove()
{
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
ve[i].clear();
in[i]=0;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&vis[i],&din[i],&dout[i]);
if(vis[i])
{
ve[din[i]].push_back(dout[i]);
in[dout[i]]++;
}
}
if(toop_sort())
{
printf("YES\n");
}
else
{
printf("NO\n");
return;
}
for(int i=1;i<=m;i++)
{
if(vis[i]||pxun[din[i]]<pxun[dout[i]])//学了拓扑排序的应该知道拓扑序小的一定是不会被拓扑序大的指到;
{
printf("%d %d\n",din[i],dout[i]);
}
else
{
printf("%d %d\n",dout[i],din[i]);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
sove();
}
return 0;
}