A:Buildings
题意:给出一组数列,设数列第一个值为X,求第一个大于X的下标,若不存在,输出-1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=105;
int a[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int maxn=a[1],pos=-1;
for(int i=2;i<=n;i++)
{
if(a[i]>maxn)
{
pos=i;
break;
}
}
cout<<pos<<endl;
return 0;
}
B:AtCoder Amusement Park
题意:给出一个容量为x的容器和一组数列,数列内的每个值为一个整体,求最小要用几个容器才能全部装完
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=105;
int a[N];
int main()
{
int n,k,x;
cin>>n>>k;
queue<int>q;
for(int i=1;i<=n;i++)
{
cin>>x;
q.push(x);
}
int cnt=0;
while(q.size())
{
int sum=0;
while(sum+q.front()<=k&&q.size())
{
sum+=q.front();
q.pop();
}
cnt++;
}
cout<<cnt<<endl;
return 0;
}
C:Sigma Problem
题意:给出一个数组,设任意两个数所组成的不重复组合数的值为x,求所以x模10^8的值为多少
解题思路:若不考虑模的情况,可以从左到右遍历,每个值的贡献为n-i(i为当前值的下标),现在将模的问题考虑进来,两个组合数的最大值为2*10^8,模10^8就是减去一个10^8。
由此可得该题可以先算出总值,然后将数组从小到大排序,从右往左遍历,找出和超过10^8的1值并减去10^8
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const ll N=3e6,mod=1e8;
ll a[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
ll sum=0;
for(int i=1;i<=n;i++)
{
sum+=a[i]*(n-1);
}
sort(a+1,a+n+1);
int l=n;
for(int i=1;i<=n;i++)
{
while(a[i]+a[l]>=mod&&l)l--;
sum-=min(n-l,n-i)*mod;
}
cout<<sum<<endl;
return 0;
}
D:Another Sigma Problem
题意:和c题一样,不过组合数的和变为字符串式的前后合并,最终所以组合数的值模998244353
解题思路:先考虑具体一个值(设为x)对整体的贡献,我们发现可以把整体分为x的前面和x的后面,x的前面对整体的贡献为x*(i-1),x的后面的值对于整体的贡献来说等于x乘以10^(具体值的长度)
防止超时,从右向左遍历,并用一个map来记录已经出现的长度的数量
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=2e6,mod=998244353;
ll a[N];
int b[50];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
memset(b,0,sizeof(b));
ll sum=0;
for(int i=n;i>=1;i--)
{
sum=(sum+a[i]*(i-1))%mod;
ll tmp=0,cnt=10;
for(int j=1;j<=20;j++)
{
tmp=(tmp+cnt*b[j])%mod;
cnt*=10;
}
sum=(sum%mod+(a[i]*tmp)%mod)%mod;
ll x=a[i];
int y=0;
while(x)
{
y++;
x/=10;
}
b[y]++;
}
cout<<sum<<endl;
return 0;
}
E:Yet Another Sigma Problem
题意:和C题一样,把数字改为字符串,把组合数的值改为,两个字符串的最长公共前缀的长度
解题思路:字典树的运用,根据题意可以构成一课字典树。在构建的同时记录出现的前缀的个数(n),每个前缀的贡献为C(2,n)=(n*(n-1)/2)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=3e5+9;
ll tr[N][30],b[N];
ll id=0;
void insert(string s)
{
int p=0;
for(int i=0;i<s.size();i++)
{
int x=s[i]-'a';
if(tr[p][x]==0)
{
tr[p][x]=++id;
}
p=tr[p][x];
b[p]++;
}
}
string s[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i];
insert(s[i]);
}
ll sum=0;
for(int i=1;i<=id;i++)
{
sum+=b[i]*(b[i]-1)/2;
}
cout<<sum<<endl;
return 0;
}
F:Tile Distance(大模拟)
G:Merchant Takahashi
题意:一个人赶集,给出车费C,和m个集市,按顺序给出每个集市的位置t和利润p(下一个集市开始于上一个集市的结束),求可以获得的最大利润
解题思路:设f[i]为到达第i个集市的最大利润,由此可得f[i]=f[j]+abs(t[i]-t[j])*c+p(0<=j<i),直接枚举会超时,可以尝试将绝对值去掉:
当t[i]<=t[j]时,f[i]=f[j]-t[j]*c+t[i]*c+p
当t[i]>t[j]时,f[i]=f[j]+t[j]*c-t[i]*c+p
由此可得只需维护f[j]-t[j]*c和f[j]+t[j]*c即可,因为涉及到单点修改,区间查询,所以这里可以用线段树来维护。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N=2e6;
const ll inf=1e18;
int n,m;
ll c;
class segt
{
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mid ((l+r)>>1)
public:
ll tr[N<<2];
void pushup(int rt)
{
tr[rt]=max(tr[lson],tr[rson]);
}
void build(int rt,int l,int r,vector<ll>&v)
{
if(l==r)
{
tr[rt]=v[l-1];
return;
}
build(lson,l,mid,v);
build(rson,mid+1,r,v);
pushup(rt);
}
void update(int rt,int l,int r,int idx,ll v)
{
if(l==r)
{
tr[rt]=max(tr[rt],v);
return;
}
if(idx<=mid)
{
update(lson,l,mid,idx,v);
}
else
{
update(rson,mid+1,r,idx,v);
}
pushup(rt);
}
ll querry(int rt,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return tr[rt];
}
ll res=-inf;
if(x<=mid)
{
res=max(res,querry(lson,l,mid,x,y));
}
if(y>mid)
{
res=max(res,querry(rson,mid+1,r,x,y));
}
return res;
}
}lsg,rsg;
int main()
{
cin>>n>>c;
vector<ll>v(n);
for(int i=0;i<n;i++)
{
v[i]=-inf;
}
v[0]=0;
lsg.build(1,1,n,v);
rsg.build(1,1,n,v);
ll ans=0;
cin>>m;
for(int i=0;i<m;i++)
{
int t;
ll p;
cin>>t>>p;
int id=t;
t--;
ll dp1=lsg.querry(1,1,n,1,id)-1ll*c*t;
ll dp2=rsg.querry(1,1,n,id,n)+1ll*c*t;
ll dp=max(dp1,dp2)+p;
ans=max(ans,dp);
lsg.update(1,1,n,id,dp+1ll*c*t);
rsg.update(1,1,n,id,dp-1ll*c*t);
}
cout<<ans<<endl;
return 0;
}