C2、Exam in BerSU (hard version)
:给定n,m.n个学生,给出第i个学生通过测验需要的时间。n个学生按编号顺序依次考试。总的测试时间超过m则考试结束,剩下的人视为考试失败。问对第1个到第n个学生,要使第i个学生通过考试,则至少要几个人考试不通过(考试不通过则耗时为0)注意每个学生的结果相互独立。
M (1≤n≤2⋅10^5,1≤n≤2⋅10^5) , ti (1≤ti≤100)
solution:首先想到贪心策略:遍历到第i个学生时,计算sum,如果sum>m则从前i-1个由大到小减,直到sum<m。所以在数据量很小时,可以排序后遍历,但现在为10^5显然不行。由题意只ti最多到100,我们是想每次都能找到当前最大的ti值,依次减。所以可以用一个数组countk[i]表示当前测试时间为k的学生有多少个,这样的话只用从大到小遍历100,而不是n了。
#include<bits/stdc++.h>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int a[200020];
int cnt[200];
int main()
{
int n,m;
cin>>n>>m;
far(i,0,n)
scanf("%d",&a[i]);
printf("0 ");
int sum=a[0];
cnt[a[0]]++;
far(i,1,n)
{
sum+=a[i];
if(sum>m)
{
int x=sum-m;
int ans=0;
for(int j=100;j>=1;--j)
{
int y=j*cnt[j];
ans+=cnt[j];
if(y>=x)
{
int z=y-x;
ans-=z/j;
break;
}
x-=y;
}
printf("%d ",ans);
}
else
printf("0 ");
cnt[a[i]]++;
}
}
D、Extra Element
theme:给定一个数组n,问删除其中哪个元素后,经过排序数组是等差数列。如果不存在,则输出-1。
(2≤n≤2⋅10^5,−10^9≤bi≤10^9)
solution:等差数列最主要的就是公差,所以先排序,注意最后求的是下标,所以记录下原下标。首先我们得确定公差。考虑a[1]-a[0],所以先判断删除1,2个元素行不行,即两次遍历即可。如果不行,则可以确定公差d=a[1]-a[0],现在开始往后遍历相邻两项和是否为d,一旦不为,假设a[i+1]-a[i]!=d,则判断a[i+2]-a[i]是否为d(注意要判断i+2是否>=n),如果=d,则说明删除排序后i+1项,如果它之后任意两项的差都为公差,则满足条件,否则输出-1.
#include<bits/stdc++.h>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
struct _a
{
int i,v;
bool operator<(_a b)const
{
return v<b.v;
}
}a[200010];
int b[200010];
int main()
{
int n;
cin>>n;
far(i,0,n)
scanf("%d",&a[i].v),a[i].i=i;
if(n<=3)
{
printf("1\n");
return 0;
}
sort(a,a+n);
far(i,0,n)
b[i]=a[i].v;
int d=b[2]-b[1];
int flag=1;
far(i,2,n-1)
{
if(b[i+1]-b[i]!=d)
{
flag=0;
break;
}
}
if(flag)
{
printf("%d\n",a[0].i+1);
return 0;
}
d=b[2]-b[0];
flag=1;
far(i,2,n-1)
{
if(b[i+1]-b[i]!=d)
{
flag=0;
break;
}
}
if(flag)
{
printf("%d\n",a[1].i+1);
return 0;
}
flag=1;
d=a[1].v-a[0].v;
int ans=1;
far(i,1,n-1)
{
if(b[i+1]-b[i]!=d)
{
// cout<<"1:"<<i<<endl;
if(i==n-2)
ans=a[n-1].i+1;
else
{
if(b[i+2]-b[i]==d)
{
for(int j=i+2;j<n-1;++j)
{
// cout<<"2:"<<j<<endl;
if(a[j+1].v-a[j].v!=d)
{
flag=0;
break;
}
}
if(flag)
ans=a[i+1].i+1;
}
else
flag=0;
}
break;
}
}
if(!flag)
printf("-1\n");
else
printf("%d\n",ans);
}
/*
5
8 4 2 6 5
10
5 5 5 5 5 5 3 5 5 5
8
1 -1 1 -1 1 -1 1 -1
*/