C Doremy’s IQ
题意:n场比赛需要vp,每场比赛难度不同,vp者有一定的智商q,如果vp到了难度大于q的比赛,智商-1,现在我们希望vp尽可能多的比赛。
输出一个长度为n的01串,第i位是1代表这场比赛vp,否则代表skip
思路:首先想到的就是,如何能在智商-1后不影响后面的比赛vp,如果产生影响,后面的比赛至少会少vp一场,所以我们干脆禁止产生影响,这样我们就统计在这个位置要vp完后面所有的比赛一共需要多少智商。如果在正序遍历的过程中,发现目前位置的智商能满足后面所有的vp,那么直接全1就行了。
#include
#define endl '\n'
using namespace std;
const int N = 1e5+100;
int a[N];
int b[N];
int main()
{
int t;
for(cin>>t;t;t--)
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
b[n]=1;
for(int i=n-1;i>=1;i--)
{
if(a[i]<=b[i+1])
b[i]=b[i+1];
else
b[i]=b[i+1]+1;
}
for(int i=1;i<=n;i++)
{
if(q>=a[i])
{
cout<<1;
}
else
{
if(q>=b[i])
{
cout<<1;
q--;
}
else
{
cout<<0;
}
}
}
cout<<endl;
}
return 0;
}
D. Difference Array
题意:给定一个长度为n的数组a,每次求出差分数组b(n-1项)后sort一下,然后替换原数组a,问最终剩下的数字是几
思路:题目给出一条非常重要的信息是:在t组测试样例中,所有a的和加起来不超过5e5。
这就给了非常强烈的提示了。
再想一想,只要a[i]和a[i-1]这俩不是x和0,必然会使得操作之后的总和至少减一,而有n个数就代表会至少缩减n-1。
0和0做差得到的dis必然是0,x和0得到也只能是x,最后剩下的就是一堆0和一个非0数x,或者是只剩下了一堆0
也就是说,这个题只要能达到最终至少有n-1个0就完活了。数组的总和是5e5,而每次操作又能最少让总和减少n-1(这里的n指目前的数列元素个数),所以复杂度不用担心。直接暴力
#include
#include
#define int long long
#define endl '\n'
#define fastio cout.tie(0);cin.tie(0);ios::sync_with_stdio(0);
using namespace std;
const int N = 1e5+100;
int n,t;
int a[N];
signed main()
{
fastio
for(cin>>t;t;t--)
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int st=1;
int con=1;
while(a[n-1])
{
con++;
int dis;
for(int i=st+1;i<=n;i++)
{
dis=a[i]-a[i-1];
a[i-1]=dis;
}
a[n]=0;
sort(a+st,a+n+1);
for(int i=st;i<=n-1;i++)
{
if(a[i]!=0)
{
st=i-1; break;
}
}
st=max(con,st);
}
cout<<a[n]<<endl;
}
return 0;
}
C. Qpwoeirut And The City
题意:给定n个数,在这些数的中间部分(除去第1和第n项)构造波峰,可以选择数组里任意的数加x,这会产生x点花费,要求在构造最多波峰的前提下花费最少。求最少花费
思路:首先波峰最多很简单。奇数个数时,我们只能让第二个数作为波峰,第三个作为波谷,第四波峰,,,以此类推
偶数时,我们画图发现,波谷的长度未必是1了,可能是两个数来当波谷。但是我们发现由第2个数当波谷,和由第2个数当波峰是两个互补的情况,也就是说我们可以用这两种情况来拼凑出一个最优情况。
这样就可以愉快地前缀和+枚举贪心来做了
#include
#define int long long
using namespace std;
const int N=1e5+100;
int a[N],b[N],c[N];
signed main()
{
int t;
for(cin>>t;t;t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
if(n&1)
{
int ans=0;
for(int i=2;i<=n-1;i+=2)
{
if(a[i]<=a[i-1]||a[i]<=a[i+1])
ans+=1+max(a[i-1],a[i+1])-a[i];
}
cout<<ans<<endl;
}
else
{
int ans;
for(int i=3;i<=n-1;i+=2)
{
if(a[i]<=a[i-1]||a[i]<=a[i+1])
c[i]=1+max(a[i-1],a[i+1])-a[i];
}
for(int i=2;i<=n-1;i+=2)
{
if(a[i]<=a[i-1]||a[i]<=a[i+1])
b[i]=1+max(a[i-1],a[i+1])-a[i];
}
for(int i=1;i<=n;i++)
{
c[i]+=c[i-1];
b[i]+=b[i-1];
}
ans=min(c[n-1],b[n-1]);
for(int i=2;i<=n-1;i++)
{
ans=min(ans,b[i]+c[n-1]-c[i+1]);
}
cout<<ans<<endl;
}
for(int i=1;i<=n;i++)
{
a[i]=b[i]=c[i]=0;
}
}
return 0;
}