http://codeforces.com/contest/1141
这次div3没打,下来做了一下也不是挺难的;
A. Game 23
题意:给出两个数n和m,问n几步可以变到m,其中只可以乘2或者乘3
解法:直接dfs
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
ll n,m;
bool flag=false;
void dfs(int x,int s)
{
if(flag||x>m)
return;
if(x==m)
{
flag=true;
cout<<s<<endl;
return;
}
dfs(x*2,s+1);
dfs(x*3,s+1);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
dfs(n,0);
if(!flag)
cout<<-1<<endl;
return 0;
}
B. Maximal Continuous Rest
题意:找到连续1的最长长度,注意可以是一个圈可以循环;
解法:直接模拟即可,没什么说的
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
int l=0,r=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
if(a[i]!=1)
break;
l++;
}
for(int i=n;i>=1;i--)
{
if(a[i]!=1)
break;
r++;
}
int tmp=0,ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]==1)
tmp++;
else
{
ans=max(tmp,ans);
tmp=0;
}
}
cout<<max(l+r,ans)<<endl;
return 0;
}
C. Polycarp Restores Permutation
题意:给n-1个数为q,qi=p(i+1)-pi,根据q求出p, 求不出时为-1,注意,p为一个排列。
做法:首先假设p1为一个随便的值不会超过范围就行,然依次推出来,在找到最小值以此基础上变到1,全部加上一个数。
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
int a[N],b[N],c[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n-1;i++)
cin>>a[i];
b[1]=0;c[1]=0;
c[0]=-2*N;
for(int i=2;i<=n;i++)
{
b[i]=a[i-1]+b[i-1];
c[i]=b[i];
}
int add=2*N;
sort(c+1,c+n+1);
c[0]=c[1]-1;
for(int i=1;i<=n;i++)
{
if(c[i]-c[i-1]!=1)
{
cout<<"-1"<<endl;
return 0;
}
add=min(add,b[i]);
}
for(int i=1;i<=n;i++)
cout<<b[i]-(add-1)<<" ";
cout<<endl;
return 0;
}
D. Colored Boots
题意:给两个字符串a和b,每个字符表示一个靴子的颜色,两个相同的字母可以配对,问号可以和任何的靴子合法配对,问两个字符串最大能匹配多少对靴子,输出每对靴子的下标。
做法:直接set维护a和b的下标,然后遍历n一一配对,就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+10;
int n,m;
char a[N],b[N],c[N];
set<int>ss1[200],ss2[200];
pair<int,int> ans[N];
vector<int>v;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(c,0,sizeof(c));
cin>>n;
cin>>a>>b;
int cnt=0;
for(int i=0;i<n;i++)
{
ss1[a[i]].insert(i);
ss2[b[i]].insert(i);
}
for(int i=0;i<n;i++)
{
int tmp=a[i];
if(tmp!='?')
{
if(ss2[tmp].size()==0&&ss2['?'].size()!=0)
{
ans[cnt].first=i;
ans[cnt++].second=*ss2['?'].begin();
c[*ss2['?'].begin()]=1;
ss2['?'].erase(ss2['?'].begin());
}
else if(ss2[tmp].size()!=0)
{
ans[cnt].first=i;
ans[cnt++].second=*ss2[tmp].begin();
c[*ss2[tmp].begin()]=1;
ss2[tmp].erase(ss2[tmp].begin());
}
}
}
for(int i=0;i<n;i++)
{
if(!c[i])
v.push_back(i);
}
set<int>::iterator it=ss1['?'].begin();
int i=0;
for(;it!=ss1['?'].end()&&i<v.size();++it)
{
ans[cnt].first=*it;
ans[cnt++].second=v[i++];
}
cout<<cnt<<endl;
for(int i=0;i<cnt;i++)
cout<<ans[i].first+1<<" "<<ans[i].second+1<<endl;
return 0;
}
E. Superhero Battle
题意:给出一个生命值h和n,n表示一个周期的行动,负号表示损失生命,正号表示恢复,问这样几次行动生命值为0;
做法:先算第一个周期,能不能在不回复的情况下杀死,然后直接算出来一个周期损失的生命值,大于等于0肯定不行了,
然后再用生命值除以损失的生命值,注意提前一两个周期在处理。
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
ll h, n, a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll sum = 0, ans = 0;
cin >> h >> n;
ll tmp = 0, maxn = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i];
}
for (int i = 1; i <= n; i++)
{
if (tmp>0)
tmp = 0;
tmp += a[i];
maxn = min(tmp, maxn);
}
tmp = h;
ans = 0;
for (int i = 1; i <= n; i++)
{
tmp += a[i];
if (tmp <= 0)
{
cout << i << endl;
return 0;
}
}
if (sum >= 0)
{
cout << "-1" << endl;
return 0;
}
ll tt = (h + maxn) / (-1*sum);
ans += tt*n;
h = h + tt*sum;
int i = 1;
while (h>0)
{
h += a[i];
ans++;
i++;
if (i>n)
i = 1;
}
cout << ans << endl;
return 0;
}
F1,F2. Same Sum Blocks
题意:给出n个数,有k个子数组不相交且区间和相同,求k的最大值
做法:我是用map直接标记一个区间和所对应的子数组。
然后暴力枚举区间和居然过了。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int a[N],sum[N];
int n;
vector<pair<int,int> >vv;
map<int,vector<pair<int,int> > >mp;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int ans=0;
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=i;j>=1;j--)
{
sum+=a[j];
if(mp[sum].size()==0||mp[sum].back().second<j)
mp[sum].push_back(make_pair(j,i));
if(i==1)
ans=sum;
if(mp[sum].size()>mp[ans].size())
ans=sum;
}
}
cout<<mp[ans].size()<<endl;
for(auto i:mp[ans])
cout<<i.first<<" "<<i.second<<endl;
return 0;
}
G. Privatization of Roads in Treeland
题意:给出一个n结点的图,然后进行边的染色,如果说一个结点相连的至少两条边是相同的颜色,那么这个结点成为不好的点,问在不好的点最多为k的情况下,最少用多少种颜色去染色,并输出染色。
做法:如果有k个不好的点,则度数第k+1大的点相连的边颜色不同,答案就是度数第k+1大的度数,然后随便用dfs跑就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int c[N],in[N];
int n,k,ans;
struct node
{
int u,v;
node(int u,int v):u(u),v(v){};
};
vector<node>g[N];
void dfs(int u,int fa,int k)
{
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].v;
if(v==fa)
continue;
if(k>ans)
k-=ans;
c[g[u][i].u]=k++;
dfs(v,u,k);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
int u,v;
for(int i=1;i<=n-1;i++)
{
cin>>u>>v;
in[u]++,in[v]++;
g[u].push_back(node(i,v));
g[v].push_back(node(i,u));
}
sort(in+1,in+n+1,greater<int>());
ans=in[k+1];
dfs(1,0,1);
cout<<ans<<endl;
for(int i=1;i<n;i++)
cout<<c[i]<<" ";
cout<<endl;
return 0;
}