比赛链接 https://codeforces.com/contest/1175
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
const ll lim=(1ll<<32)-1;
int q;
ll s[maxn],top;
int main()
{
ll ans=0;
ll times=1;
s[0]=1;
cin>>q;
while(q--)
{
string op;
cin>>op;
if(op[0]=='a')
{
ans+=s[top];
if(ans>lim)
{
puts("OVERFLOW!!!");
return 0;
}
}
else if(op[0]=='f')
{
int x;
cin>>x;
s[++top]=min(s[top-1]*x,lim+1);
}
else if(op[0]=='e')
top--;
}
cout<<ans<<"\n";
return 0;
}
题意:给定一个数组 a ,找到一个 x 使得第 k + 1个 x与 a i a_i ai的绝对值最小
思路:找到距离最近的 k+1个数即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+10;
const ll lim=(1ll<<32)-1;
int t,n,k;
int a[maxn];
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>a[i];
ll dis=9e18,ans;
for(int i=1;i+k<=n;++i)
{
if(dis>a[i+k]-a[i])
{
dis=a[i+k]-a[i];
ans=(a[i+k]+a[i])/2;
}
}
cout<<ans<<"\n";
}
return 0;
}
题意: 给定长度为 n 个数组,划分成 k 个非空子集,要求 ∑ i = 1 n a i × f ( i ) \sum_{i=1}^n a_i\times f(i) ∑i=1nai×f(i)最大。f(i)表示第 i 个元素在第 f(i)个子集
思路: 在 n -1 个前缀中删去最小的 k -1 个前缀。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
const ll lim=(1ll<<32)-1;
int n,k;
int a[maxn];
ll pref[maxn];
int main()
{
ll sum=0;
cin>>n>>k;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i)
{
pref[i]=pref[i-1]+a[i];
sum+=a[i];
}
sort(pref+1,pref+n);
ll ans=sum*k;
for(int i=1;i<=k-1;++i)
{
ans-=pref[i];
}
cout<<ans<<"\n";
return 0;
}
题意:给定 n 条线段,给出 m 个区间的询问,问最少需要多少条线段可以覆盖当前询问的区间。 ( n , m ≤ 2 e 5 , l i , r i ≤ 5 e 5 ) (n,m\le 2e5 , l_i,r_i\le 5e5) (n,m≤2e5,li,ri≤5e5)
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5e5;
int n,m,maxr;
int dp[maxn+10][25];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
int l,r;
scanf("%d%d",&l,&r);
dp[l][0]=max(dp[l][0],r);
maxr=max(maxr,r);
}
for(int l=1;l<=maxr;++l)
dp[l][0]=max(dp[l][0],max(l,dp[l-1][0]));
for(int j=1;j<=20;++j)
for(int i=0;i<=maxr;++i)
dp[i][j]=dp[dp[i][j-1]][j-1];
while(m--)
{
int l,r;
ll ans=0;
scanf("%d%d",&l,&r);
if(r>maxr||dp[l][20]<r)
{
puts("-1");
continue;
}
for(int i=20;i>=0;--i)
if(dp[l][i]<r)
l=dp[l][i],ans+=(1<<i);
ans++;
printf("%lld\n",ans);
}
return 0;
}
题意:给以一个长度为 n 的数组,求区间 [ l , r ] [l,r] [l,r] 是排列的个数
思路:
实现:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
int n;
int a[maxn],last[maxn];
int dp[maxn][20],r[maxn];
void init()
{
for(int i=1;i<=n;++i) dp[i][0]=a[i];
for(int j=1;(1<<j)<=n;++j)
for(int i=1;i+(1<<j)-1<=n;++i)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
int queryMax(int l,int r)
{
int k=log2(r-l+1);
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
r[n+1]=n;
for(int i=n;i>=1;--i)
{
if(last[a[i]]) r[i]=min(r[i+1],last[a[i]]-1);
else r[i]=r[i+1];
last[a[i]]=i;
}
init();
int ans=0;
for(int i=1;i<=n;++i)
{
int j=i;
while(j<=r[i])
{
if(queryMax(i,j)==j-i+1) ans++,j++;
else j=i+queryMax(i,j)-1;
}
}
printf("%d\n",ans);
return 0;
}
学长的分治代码
#include <bits/stdc++.h>
using namespace std;
#define MAXNUM 333333
#define rep(i,s,t) for(int i=s;i<t;i++)
#define pii pair<int,int>
int per[MAXNUM],pos[MAXNUM],f[20][MAXNUM],LOG[MAXNUM],n;
pii fnum[20][MAXNUM],num[MAXNUM];
void getlist()
{
LOG[0] = -1;
for (int i = 1; i <= n; i++)
LOG[i] = LOG[i / 2] + 1;
}
template<typename T> void create(T f[][MAXNUM],T num[])
{
for (int j = 1; j <= n; j++)
f[0][j] = num[j];
for (int i = 1; i <= 20; i++)
for (int j = 1; j + (1 << i) - 1 <= n; j++)
f[i][j] = max(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
}
template<typename T> T query(T f[][MAXNUM],int qleft, int qright)
{
int nLog = LOG[qright - qleft + 1];
return max(f[nLog][qleft], f[nLog][qright - (1 << nLog) + 1]);
}
int res;
void solve(int l,int r)
{
if(l>r)return;
pii p=query(fnum,l,r);
int mid=(l+r)/2;
if(p.second<=mid)
{
rep(i,l,p.second+1)
if(i+p.first-1<=r&&i+p.first-1>=p.second&&query(f,i,i+p.first-1)<i)
res++;
}
else{
rep(i,p.second,r+1)
if(i-p.first+1>=l&&i-p.first+1<=p.second&&query(f,i-p.first+1,i)<i-p.first+1)
res++;
}
solve(l,p.second-1),solve(p.second+1,r);
}
int main()
{
scanf("%d",&n);
getlist();
rep(i,1,n+1)scanf("%d",&num[i].first),num[i].second=i;
rep(i,1,n+1)
per[i]=pos[num[i].first],pos[num[i].first]=i;
create(f,per),create(fnum,num);
solve(1,n);printf("%d\n",res);
}