A Three swimmers
题意 三个人每人游一个来回时间分别是a、b、c,那么在 a、b、c的倍数时间点上 三个人均会在左边的点,题目问你p时刻来 还要等多久最快遇到三个人 1e18 除法判断是否整除相减即可
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 100005;
priority_queue<pair<int,int> > q;
int ans[MAX_N],arr[MAX_N];
int num = 0;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
num = 0;
int n;
scanf("%d",&n);
for(int i = 1;i<=n;++i)
{
scanf("%d",&arr[i]);
q.push(make_pair(arr[i],i));
}
int maxx = n;
while(!q.empty())
{
pair<int,int> top = q.top();
q.pop();
if(top.second>maxx) continue;
int xb = top.second;
while(xb<=maxx)
{
ans[++num] = arr[xb];
xb++;
}
maxx = top.second-1;
}
for(int i = 1;i<=n;++i)
{
i==n?printf("%d\n",ans[i]):printf("%d ",ans[i]);
}
}
return 0;
}
BCard Deck
按照卡牌顺序你每次选k张,然后将k张从最下面反过来放到新桌子上获得收益,收益因为是n的次方,我们发现每个卡牌是小于等于n,所以你把大的放在最下面获得收益最高,如果每个卡牌不是小于等于n 需要dp计算
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 100005;
priority_queue<pair<int,int> > q;
int ans[MAX_N],arr[MAX_N];
int num = 0;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
num = 0;
int n;
scanf("%d",&n);
for(int i = 1;i<=n;++i)
{
scanf("%d",&arr[i]);
q.push(make_pair(arr[i],i));
}
int maxx = n;
while(!q.empty())
{
pair<int,int> top = q.top();
q.pop();
if(top.second>maxx) continue;
int xb = top.second;
while(xb<=maxx)
{
ans[++num] = arr[xb];
xb++;
}
maxx = top.second-1;
}
for(int i = 1;i<=n;++i)
{
i==n?printf("%d\n",ans[i]):printf("%d ",ans[i]);
}
}
return 0;
}
C. Maximum width
定义完美字符串为T每个字符按顺序均属于S 两个字符间最长距离为所求值,一开始想到可能和长度有关 压位dp,但是不太好定义 于是定义出如下dp含义 dp[i][2] - dp[i][0] 代表T中第 i 个字符属于S最左能在什么位置 当然要比dp[i-1][0] 大,那么dp[i][1] 代表T中第 i 个字符属于S最右能在什么位置 当然要比 dp[i+1][1] 小 枚举点求答案
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
const int MAX_N = 200005;
priority_queue<pair<int,int> > q;
long long dp[MAX_N][2];
char str[MAX_N],str_[MAX_N];
vector<int> vt[35];
int main()
{
int n,m,ans = 0;
scanf("%d%d",&n,&m);
scanf("%s",str+1);
for(int i = 1;i<=n;++i)
{
vt[str[i]-'a'+1].push_back(i);
}
scanf("%s",str_+1);
for(int i = 1;i<=m;++i)
{
dp[i][0] = 0x3f3f3f3f;
dp[i][1] = 0;
}
dp[0][0] = 0,dp[m+1][1] = 0x3f3f3f3f;
for(int i = 1;i<=m;++i)
{
int l = 0,r = vt[str_[i]-'a'+1].size()-1;
while(l<=r)
{
int mid = (l+r)/2;
if(vt[str_[i]-'a'+1][mid] > dp[i-1][0]) r = mid - 1;
else l = mid + 1;
}
dp[i][0] = vt[str_[i]-'a'+1][l];
}
for(int i = m;i>=1;--i)
{
int l = 0,r = vt[str_[i]-'a'+1].size()-1;
while(l<=r)
{
int mid = (l+r)/2;
if(vt[str_[i]-'a'+1][mid] < dp[i+1][1]) l = mid+1;
else r = mid - 1;
}
dp[i][1] = vt[str_[i]-'a'+1][r];
}
dp[m+1][1] = 0;
for(int i = 1;i<=m;++i)
{
ans = max(1ll*ans,dp[i+1][1]-dp[i][0]);
}
printf("%d\n",ans);
return 0;
}
D. Genius’s Gambit
当a=0或者b=1情况比较明显
手完出了 k<=a 与 k <=b-1的情况,写了个暴力归纳k<=a+b-2的情况 a+b-2可以将 k<=a 与 k<=b-1结合起来玩
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAX_N = 200025;
char str[MAX_N];
int main()
{
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
if(a==0)
{
if(k==0)
{
printf("Yes\n");
for(int i = 1;i<=b;++i) printf("1");printf("\n");
for(int i = 1;i<=b;++i) printf("1");printf("\n");
}
else
{
printf("No\n");
}
}
else if(b==1)
{
if(k==0)
{
printf("Yes\n");
for(int i = 1;i<=b;++i) printf("1");for(int i = 1;i<=a;++i) printf("0");printf("\n");
for(int i = 1;i<=b;++i) printf("1");for(int i = 1;i<=a;++i) printf("0");printf("\n");
}
else
{
printf("No\n");
}
}
else
{
if(k<=a)
{
printf("Yes\n");
for(int i = 1;i<=b-1;++i) printf("1");printf("1");for(int i = 1;i<=k;++i) printf("0");for(int i = 1;i<=a-k;++i) printf("0");printf("\n");
for(int i = 1;i<=b-1;++i) printf("1");for(int i = 1;i<=k;++i) printf("0");printf("1");for(int i = 1;i<=a-k;++i) printf("0");printf("\n");
}
else if(k<=b-1)
{
printf("Yes\n");
printf("1");for(int i = 1;i<=a-1;++i) printf("0");for(int i = 1;i<=k;++i) printf("1");printf("0");for(int i = k+2;i<=b;++i) printf("1");printf("\n");
printf("1");for(int i = 1;i<=a-1;++i) printf("0");printf("0");for(int i = 1;i<=k;++i) printf("1");for(int i = k+2;i<=b;++i) printf("1");printf("\n");
}
else if(k<=a+b-2)
{
int len = 0;
printf("Yes\n");
for(int i = 1;i<=b;++i) printf("1");for(int i = 1;i<=a;++i) printf("0");printf("\n");
for(int i = 1;i<=b-1;++i) str[++len] = '1';
int xb = b;
for(int i = 1;i<=a;++i) str[++len] = '0';
str[++len] = '1';
for(int i = 1;i<=k-a;++i) swap(str[xb],str[xb-1]),xb--;
printf("%s\n",str+1);
}
else
{
printf("No\n");
}
}
return 0;
}
E. Almost Fault-Tolerant Database
这题给你
n
∗
m
n*m
n∗m 个数,问你能否找到一行
m
m
m 个数,使得这
m
m
m 个数与每一行不同的数不超过
2
2
2 个
我们先考虑答案肯定和第一行不超过两个数(如果存在) 那么我们去拿第一行假设作为答案与其余行求
m
a
x
d
i
f
f
maxdiff
maxdiff 如果
m
a
x
d
i
f
f
maxdiff
maxdiff >=
5
5
5 肯定无解,因为你只能换两个位置
5
−
2
=
3
>
=
2
5-2=3 >= 2
5−2=3>=2 那么当
m
a
x
d
i
f
f
<
=
2
maxdiff <= 2
maxdiff<=2 肯定输出第一行本身 如果
m
a
x
d
i
f
f
=
4
maxdiff = 4
maxdiff=4 则交换其中两个元素,
m
a
x
d
i
f
f
=
3
maxdiff=3
maxdiff=3 比较麻烦,先交换一个,然后看是否满足情况 如果继续
m
a
x
d
i
f
f
=
3
maxdiff = 3
maxdiff=3 则做组合交换
3
∗
3
3*3
3∗3 情况,题解说
3
3
3 种情况 可能还是有不同的地方 另外代码也写的不够美观 感觉定义的太随意了 代码就越来越臃肿
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<stack>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
using namespace std;
#define ll long long
const int MAX_N = 250025;
vector<int> vt[MAX_N];
int ans[MAX_N],cnt[MAX_N],maxx,xb,n,m,tmp[5],tmpLen,maxx_,xb_,tmp_[5],tmpLen_,maxx__,xb__;
void findDiff()
{
maxx = -1;
for(int i = 1;i<=n;++i) cnt[i] = 0;
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
if(vt[i][j]!=ans[j]) cnt[i]++;
}
if(cnt[i]>maxx)
{
maxx = cnt[i];
xb = i;
}
}
}
void findDiffOne()
{
maxx_ = -1;
for(int i = 1;i<=n;++i) cnt[i] = 0;
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
if(vt[i][j]!=ans[j]) cnt[i]++;
}
if(cnt[i]>maxx_)
{
maxx_ = cnt[i];
xb_ = i;
}
}
}
void findDiffTwo()
{
maxx__ = -1;
for(int i = 1;i<=n;++i) cnt[i] = 0;
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
if(vt[i][j]!=ans[j]) cnt[i]++;
}
if(cnt[i]>maxx__)
{
maxx__ = cnt[i];
xb__ = i;
}
}
}
void GOOD()
{
printf("Yes\n");
for(int i = 1;i<=m;++i)
{
i==m?printf("%d\n",ans[i]):printf("%d ",ans[i]);
}
}
bool gao(int x,int y,int initXb)
{
for(int i = 1;i<=m;++i) ans[i] = vt[1][i];
ans[tmp[x]] = vt[initXb][tmp[x]];
ans[tmp[y]] = vt[initXb][tmp[y]];
findDiff();
if(maxx<=2)
{
return true;
}
return false;
}
bool gaoOne(int x)
{
ans[tmp_[x]] = vt[xb_][tmp_[x]];
findDiffTwo();
if(maxx__<=2)
{
return true;
}
return false;
}
int main()
{
int x;
scanf("%d%d",&n,&m);
for(int i = 1;i<=n;++i) vt[i].push_back(-1);
for(int i = 1;i<=n;++i)
{
for(int j = 1;j<=m;++j)
{
scanf("%d",&x);
vt[i].push_back(x);
}
}
for(int i = 1;i<=m;++i) ans[i] = vt[1][i];
findDiff();
if(maxx<=2)
{
GOOD();
}
else if(maxx>=5)
{
printf("No\n");
}
else if(maxx==3)
{
tmpLen = 0;
for(int i = 1;i<=m;++i)
{
if(ans[i]!=vt[xb][i]) tmp[++tmpLen] = i;
}
for(int i = 1;i<=tmpLen;++i)
{
for(int j = 1;j<=m;++j) ans[j] = vt[1][j];
ans[tmp[i]] = vt[xb][tmp[i]];
findDiffOne();
if(maxx_<=2)
{
GOOD();
return 0;
}
if(maxx_>3)
{
continue;
}
tmpLen_ = 0;
for(int j = 1;j<=m;++j) if(ans[j]!=vt[xb_][j]) tmp_[++tmpLen_] = j;
for(int j = 1;j<=tmpLen_;++j)
{
int lastOne = ans[tmp_[j]];
if(gaoOne(j))
{
GOOD();
return 0;
}
else
{
ans[tmp_[j]] = lastOne;
}
}
}
printf("No\n");
}
else
{
tmpLen = 0;
for(int i = 1;i<=m;++i)
{
if(ans[i]!=vt[xb][i]) tmp[++tmpLen] = i;
}
int initXb = xb;
if(gao(1,2,initXb)||gao(1,3,initXb)||gao(1,4,initXb)||gao(2,3,initXb)||gao(2,4,initXb)||gao(3,4,initXb))
{
GOOD();
}
else
{
printf("No\n");
}
}
return 0;
}