A. Working Week
题意:给我们一个数n,代表这一个长度是n并且首尾相连的环,而且第n天是休息日,我们的任务是找到另外的两个休息日,并且任意两个休息日不相邻,使得分为的三段连续上班日的长度l1,l2,l3,并且ans=min(|l1-l2|,|l2-l3|,|l3-l1|)
思路:我们可以想到用二分答案得思想,因为取最小值不难发现满足二分得条件,所以我们枚举最小长度,然后我们通过构造可以得出l1,l2,l3,之后再判断是否合法即可
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<unordered_map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstdlib>
#include<stack>
#define forxn(i,a,n) for(int i=a;i<n;i++)
#define fordn(i,a,n) for(int i=a;i<=n;i++)
#define fornd(i,n,a) for(int i=n;i>=1;i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+7, M=110 , INF=0x3f3f3f3f;
const double eps=0;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*b/gcd(a,b);}
// int f[N];
// int find(int x) {if(f[x]!=x) f[x]=find(f[x]);return f[x];}
// int h[N],e[N],ne[N],idx;
// void add(int a,int b,int c) {e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;}
// void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++;}
int T;
int n,m,k;
bool check(int mid) {
int l1=1,l2=mid+1,l3=n-mid-5;
if(abs(l2-l1)>=mid&&abs(l3-l1)>=mid&&abs(l3-l2)>=mid) return true;
else return false;
}
void solve() {
scanf("%d",&n);
if(n==6) {
printf("0\n");
return ;
}
int l=0,r=n;
while(l<r) {
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
int main() {
scanf("%d",&T);
while(T--) solve();
return 0;
}
B. Tea with Tangerines
题意:给我们一个长度是n得数组,然后对于一个数ai我们可以通过一次操作将它分成两个数,使得这两个数得和是ai,然后问我们最小得操作次数,使得所有得数对(ai,aj)满足ai*2>aj
思路:首先找到整个数组得最小值,那么对于其他得所有数都不能超过2*min-1,所以我们直接用ai除以这个数,但是如果它是他的倍数,则需要再减去1,因为相等时满足条件的
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<unordered_map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstdlib>
#include<stack>
#define forxn(i,a,n) for(int i=a;i<n;i++)
#define fordn(i,a,n) for(int i=a;i<=n;i++)
#define fornd(i,n,a) for(int i=n;i>=1;i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=110 , M=110 , INF=0x3f3f3f3f;
const double eps=0;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*b/gcd(a,b);}
// int f[N];
// int find(int x) {if(f[x]!=x) f[x]=find(f[x]);return f[x];}
// int h[N],e[N],ne[N],idx;
// void add(int a,int b,int c) {e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;}
// void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++;}
int T;
int n,m,k;
int w[N];
void solve() {
scanf("%d",&n);
int minn=2e9;
fordn(i,1,n) scanf("%d",&w[i]),minn=min(minn,w[i]);
int res=0;
int t=minn*2-1;
fordn(i,1,n) res+=w[i]/t-(w[i]%t==0);
printf("%d\n",res);
}
int main() {
scanf("%d",&T);
while(T--) solve();
return 0;
}
C. Phase Shift
题意:给我们一个由小写字母构成的字符串,然后让我们构造一个由1~26个小写字母围成的圈,然后把给定的字符串中的每个字母替换为在这个圈上对应的相同字母的顺时针下一个字母,问我们这个字符串在替换完之后能够变成的最小的字典序
思路:我们便利整个字符串,然后我们需要用到两个数组,一个是f[i]代表如果由a->b则f[b]=a,另一个是mp[i]代表着当前i需要替换成的字符,如果没有规定则为0,然后在遍历到t字符时,如果mp[t]存在,则直接进行修改,否则我们需要给他分配一个目前字典序最小的字母 ,我们从头开始遍历,因为我们是需要将t->last,那么last必需还没有被分配过,所以并且它不能是当前链上最开头的那个点,否则则形成环,于原来所有的围成一个圈矛盾,所以还需要find(t)!=find(last),最后还有一种情况就是所有的字母都有后继但是最后一个字母没有,所以我们只需要把它于第一个字母连上即可
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<unordered_map>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstdlib>
#include<stack>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=1e5+7, M=110 , INF=0x3f3f3f3f;
const double eps=0;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*b/gcd(a,b);}
// int f[N];
int f[30];
int find(int x) {if(f[x]!=x) f[x]=find(f[x]);return f[x];}
// int h[N],e[N],ne[N],idx;
// void add(int a,int b,int c) {e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;}
// void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++;}
int T;
int n,m,q;
int mp[30];
char str[N];
char ans[N];
void solve() {
memset(mp,0,sizeof mp);
scanf("%d",&n);
scanf("%s",str+1);
for(int i=1;i<=26;i++) f[i]=i;
for(int i=1;i<=n;i++) {
int t=str[i]-96;
if(!mp[t]) {
int last=1;
int k=find(t);
while(k==find(last)||f[last]!=last) {
last++;
if(last>26) break;
}
if(last>26) {
int s=find(1);
mp[t]=s;
}else {
mp[t]=last;
f[last]=t;
}
}
ans[i]=mp[t];
}
for(int i=1;i<=n;i++) printf("%c",ans[i]+96);
printf("\n");
}
int main() {
scanf("%d",&T);
while(T--) solve();
return 0;
}