J
题意:给定长度为n的数组,从中选择元素(可以不选),若选择元素ai,则每个长度为i的区间内至多只能选择2个元素。
思路:设我们选择下标最大的元素a[p],那么[1,p]区间内也最多只能选2个。所以我们最多只能选2个。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
int a[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
cout<<max({a[n],a[n]+a[n-1],0})<<'\n';
}
signed main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
C
题意:给定a,b,c。有c道题需要做,有两种操作,(1)克隆自己,花费a分钟。(2)解决一道题,花费b分钟。问最少需要多少分钟做完。
思路:c<=1e9.最多克隆30次。枚举克隆次数
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
ll a,b,c;
void solve()
{
cin>>a>>b>>c;
ll ans=1e18;
for(int i=0;i<=30;i++)
{
ll t=1<<i;
ll tem=(c+t-1)/t;
ans=min(ans,a*i+tem*b);
}
cout<<ans<<'\n';
}
signed main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
F
题意:有n只3人队伍,酒店中单人间的价格是c1,双人间的价格是c2.每间房间只能入住同一只队伍且性别相同的人。问最少花费。
思路:模拟
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n,c1,c2;
void solve()
{
cin>>n>>c1>>c2;
int ans=0;
for(int i=1;i<=n;i++)
{
string s;
cin>>s;
if(s[0]==s[1]||s[0]==s[2]||s[1]==s[2])
{
ans+=min(c2,2*c1);
ans+=min(c1,c2);
}
else
{
ans+=min(3*c1,3*c2);
}
}
cout<<ans<<'\n';
}
signed main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
G
题意:给定n个字符串。一个字符串s称为good当且仅当s的所有子串全都是给定的字符串。问最长的good串的长度。
思路:一个串s[1]s[2]...s[n]称为good,当且仅当以下两个串都是good的。
s[1]s[2]...s[n-1]
s[2]s[3]...s[n]
我们可以先把字符串按长度排序,然后判断每个串是否是good的,是我们就把它放到set中。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
set<string>S;
string t[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>t[i];
sort(t+1,t+n+1,[](const string &a,const string &b){return a.size()<b.size();});
int ans=0;
for(int i=1;i<=n;i++)
{
if(t[i].size()==1||(S.count(t[i].substr(0,t[i].length()-1))&&S.count(t[i].substr(1))))
{
S.insert(t[i]);
ans=max(ans,(int)t[i].length());
}
}
cout<<ans<<'\n';
}
signed main()
{
//ios;
int _t=1;
//cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
L
题意:给定一棵以1为根的树,将这棵树划分成若干个集合,满足在每个集合内,要么任意两点间存在祖先关系,要么任意两点间都没有祖先关系。
思路:每个集合要么是一条链,要么是不同子树中的许多点。
长链剖分
显然我们选一条链作为一个集合时,那么将这条链取到叶子是最优的。
设我们长链剖分得到p条链,每条链的长度为pl[i]
当我们全用第二种集合来划分时,那么答案即为树的最大深度。这个答案也可以看成将所有链起点水平放置,同一行中的点划分成一个集合。答案也就是最长链的长度。
再考虑选择一些长链作为第一种集合,因为第二类集合的答案是 剩余链中的最大长度,所以第一类集合选择最长的链最优。
我们将所有链按长度从大到小排序。枚举我们选择前i条链作为第一类集合,剩余的作为第二类集合,那么答案就是max(i+lp[i+1])
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
int n;
vector<int>g[N],lp;
int son[N],len[N];
void dfs1(int u)
{
for(int v:g[u])
{
dfs1(v);
if(len[v]>len[son[u]]) son[u]=v;
}
len[u]=len[son[u]]+1;
}
void dfs2(int u,int l)
{
if(!son[u]) lp.push_back(l);
else
{
dfs2(son[u],l+1);
for(int v:g[u])
if(v!=son[u])
dfs2(v,1);
}
}
void solve()
{
lp.clear();
cin>>n;
for(int i=1;i<=n;i++)
{
g[i].clear();
son[i]=0,len[i]=0;
}
for(int i=2;i<=n;i++)
{
int u;
cin>>u;
g[u].push_back(i);
}
dfs1(1);
dfs2(1,1);
sort(lp.begin(),lp.end(),greater<int>());
int ans=lp.size();
for(int i=0;i<lp.size();i++)
ans=min(ans,i+lp[i]);
cout<<ans<<'\n';
}
signed main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}
E
题意:
思路:打表发现与f(x)的值与x的三进制有关,若三进制下每有一个2,答案加3;每有一个1,答案加2;每有一个0,答案加1.我们让x从下界l开始改变,枚举从哪一位开始改变。只有当R的某一位大于L的对应位时才可以开始改变。当可以改变时,若当前从第i位开始改变,若R该位上是2,那么我们可以让x该位为1,后面全为2;若R该位上是1,那么我们让x该位为0,后面全2.(注意x不能有前置0)
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define PII pair<int,int>
typedef long long ll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
using namespace std;
ll l,r;
int ql[N],qr[N];
int cntl,cntr;
void solve()
{
cntl=cntr=0;
cin>>l>>r;
while(l)
{
ql[++cntl]=l%3;
l/=3;
}
while(r)
{
qr[++cntr]=r%3;
r/=3;
}
ll ret=0,ans=0;
bool f=0;
for(int i=cntr;i>=1;i--)
{
if(qr[i]>ql[i]) f=1;
if(f)
{
if(qr[i]==2)
{
ret=max(ret,ans+2+(i-1)*3);
}
else if(qr[i]==1)
{
if(i==cntr) ret=max(ret,ans+(i-1)*3);
else ret=max(ret,ans+1+(i-1)*3);
}
}
if(qr[i]==2) ans+=3;
else if(qr[i]==1) ans+=2;
else ans+=1;
}
cout<<max(ans,ret)<<'\n';
while(cntl) ql[cntl--]=0;
}
signed main()
{
//ios;
int _t=1;
cin>>_t;
while(_t--) solve();
system("pause");
return 0;
}