A. Game 23
如果m可以整除n,那么判断m/n是否只由2和3相乘得到。
#include "bits/stdc++.h"
using namespace std;
int main() {
int n,m;
cin>>n>>m;
int a=m/n;
if(a*n!=m){
printf("-1\n");
return 0;
}
int a2=0,a3=0;
while(a%2==0){
a2++;
a/=2;
}
while(a%3==0){
a3++;
a/=3;
}
if(a!=1)
{
printf("-1\n");
return 0;
}
printf("%d\n",a2+a3);
}
B. Maximal Continuous Rest
直接找最长连续,特判首尾即可。
#include "bits/stdc++.h"
using namespace std;
int a[200004];
int main() {
int n;
cin>>n;
for (int i = 1; i <= n; ++i) {
cin>>a[i];
}
int ans=0;
int len=0;
for (int i = 1; i <= n; ++i) {
if(a[i]==1)len++;
else
{
ans=max(ans,len);
len=0;
}
}
int len1=0,len2=0;
for (int i = 1; i <= n; ++i) {
if(a[i]==1)len1++;
else break;
}
for (int i = n; i >= 1; --i) {
if(a[i]==1)len2++;
else break;
}
ans=max(ans,min(len1+len2,n));
printf("%d\n",ans);
}
C. Polycarp Restores Permutation
将差分数组还原,第一个值的取值可以决定整体,那么还原后排序,判断是否满足条件,最后加上差值。
#include "bits/stdc++.h"
using namespace std;
int a[200004];
int b[200004];
int c[200004];
int main() {
int n;
cin>>n;
for (int i = 1; i <= n-1; ++i) {
cin>>a[i];
}
b[1]=0;
c[1]=0;
for (int i = 2; i <= n; ++i) {
b[i]=b[i-1]+a[i-1];
c[i]=b[i];
}
sort(c+1,c+n+1);
int ok=1;
for (int i = 2; i <= n; ++i) {
if(i-c[i]!=i-1-c[i-1]){
ok=0;
break;
}
}
if(ok)
{
int d=1-c[1];
for (int i = 1; i <= n; ++i) {
printf("%d ",b[i]+d);
}
puts("");
}
else puts("-1");
}
D. Colored Boots
瞎JB模拟,没啥好说的。
#include "bits/stdc++.h"
using namespace std;
vector<pair<int,int>>ans;
bool vis[1500004];
int main() {
int n;
cin>>n;
string s1,s2;
cin>>s1>>s2;
memset(vis,0, sizeof(vis));
unordered_map<char,vector<int>>mp;
for (int i = 0; i < n; ++i) {
mp[s1[i]].push_back(i);
}
vector<int>v;
for (int i = 0; i < n; ++i) {
if(s2[i]!='?'&&mp[s2[i]].size())
{
ans.push_back({i,mp[s2[i]][0]});
vis[mp[s2[i]][0]]=1;
mp[s2[i]].erase( mp[s2[i]].begin());
}
else if((s2[i]!='?'&&mp['?'].size()))
{
ans.push_back({i,mp['?'][0]});
vis[mp['?'][0]]=1;
mp['?'].erase(mp['?'].begin());
}
else if(s2[i]=='?')v.push_back(i);
}
int cnt=0;
for (int i = 0; i < n&&cnt<v.size(); ++i) {
if(!vis[i])
{
ans.push_back({v[cnt++],i});
}
}
printf("%d\n",ans.size());
for (int i = 0; i < ans.size(); ++i) {
printf("%d %d\n",ans[i].second+1,ans[i].first+1);
}
}
E. Superhero Battle
循环,没啥可讲的。
#include "bits/stdc++.h"
using namespace std;
long long a[200004];
int main() {
long long h,n;
cin>>h>>n;
for (int i = 0; i < n; ++i) {
cin>>a[i];
}
long long pre=0,base=8e18;
for (int i = 0; i < n; ++i) {
pre+=a[i];
base=min(base,pre);
}
long long left=h+base;
if(left<=0)
{
long long ans=0;
for (int i = 0; i < n; ++i) {
h+=a[i];
ans++;
if(h<=0)break;
}
printf("%lld\n",ans);
}
else
{
if(pre>=0)printf("-1\n");
else
{
long long ans=0;
ans+=n*(left/(-pre));
h-=(left/(-pre))*(-pre);
while(h>0)
for (int i = 0; i < n; ++i) {
h+=a[i];
ans++;
if(h<=0)break;
}
printf("%lld\n",ans);
}
}
}
F1. Same Sum Blocks (Easy) && F2. Same Sum Blocks (Hard)
因为只能找连续的区间,所以能得到的区间个数只有n*(n+1)个。
最多只有2250000个区间,预处理前缀和,把所有区间的信息求出来:左右端点,sum
按sum值分类,然后问题就变成了:若干个区间,不能重叠,最多能安置几个区间。
将区间按照左端点排序,记录一个已覆盖区间的右端点值R,每当一个新区间要加进来时:
如果l>R,那么将该区间加入
如果r<R,那么该区间可以代替上一个区间
之后乱搞就完事儿了。
#include "bits/stdc++.h"
using namespace std;
int a[1504];
int pre[1504];
struct node
{
int l,r,w;
bool friend operator < (node &a,node &b)
{
return a.w<b.w;
}
}b[2250004];
bool cmp(node &a,node &b)
{
if(a.l==b.l)return a.r<b.r;
else return a.l<b.l;
}
int main() {
int n;
cin>>n;
pre[0]=0;
for (int i = 1; i <= n; ++i) {
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
int cnt=0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
b[cnt++]={j,i,pre[i]-pre[j-1]};
}
}
sort(b,b+cnt);
int l=0,r=0;
int ans=0;
vector<pair<int,int>>v;
vector<pair<int,int>>anss;
for (l = 0; l < cnt; l=r) {
for (r = l; r < cnt; ++r) {
if(b[r].w!=b[l].w)break;
}
sort(b+l,b+r,cmp);
int sum=0;
int R=0;
v.clear();
for (int i = l; i < r; ++i) {
if(b[i].l>R){
sum++;
R=b[i].r;
v.push_back({b[i].l,b[i].r});
}
else if(b[i].r<R)
{
R=b[i].r;
v.erase(v.end()-1);
v.push_back({b[i].l,b[i].r});
}
}
if(sum>ans)
{
ans=sum;
anss=v;
}
}
printf("%d\n",ans);
for (int i = 0; i < anss.size(); ++i) {
printf("%d %d\n",anss[i].first,anss[i].second);
}
return 0;
}
G. Privatization of Roads in Treeland
有K个城市可以有多个公司,那么预处理每个点的度,按照从大到小的顺序找出K个城市,此时就满足最优。
然后跑一个dfs,当跑到被安排的城市时,其连接的边全部赋值为1,当跑到没有被安排的城市时,依次给边赋值,注意不能与上一个城市所操作的边有重复的值,所以这里记录一个前缀prec即可。
这里我直接对point结构体排序T了,估计是因为vector的锅。把里面的v.size和u单独提出来操作,就只跑了200+ms。
#include "bits/stdc++.h"
using namespace std;
struct node
{
int u,id;
};
struct point
{
vector<node>v;
int u;
}a[200004];
struct xxx
{
int num,u;
}b[200004];
bool isok[200004];
int line[200004];
bool cmp(xxx a,xxx b)
{
return a.num>b.num;
}
void dfs(int u,int pre,int prec)
{
//if(u==pre)return;
int cnt=1;
if(isok[u])
for (int i = 0; i < a[u].v.size(); ++i) {
if(a[u].v[i].u==pre)continue;
line[a[u].v[i].id]=1;
dfs(a[u].v[i].u,u,1);
}
else
for (int i = 0; i < a[u].v.size(); ++i) {
if(a[u].v[i].u==pre)continue;
if(cnt==prec)cnt++;
line[a[u].v[i].id]=cnt;
dfs(a[u].v[i].u,u,cnt);
cnt++;
}
}
int main() {
int n,k;
cin>>n>>k;
for (int i = 0; i < n-1; ++i) {
int x,y;
scanf("%d%d",&x,&y);
a[x].v.push_back({y,i+1});
a[y].v.push_back({x,i+1});
}
memset(isok,false, sizeof(isok));
for (int i = 1; i <= n; ++i) {
b[i].u=i;
b[i].num=a[i].v.size();
}
sort(b+1,b+n+1,cmp);
for (int i = 1; i <= k; ++i) {
isok[b[i].u]=1;
}
int ans=b[k+1].num;
dfs(1,-1,-1);
printf("%d\n",ans);
for (int i = 1; i <= n-1; ++i) {
printf("%d ",line[i]);
}
puts("");
return 0;
}
感觉这场打了的话可以拿一个不错的rk,可惜啊(;´д`)ゞ打比赛是不可能打比赛的,只有补题才能勉强维持生活