国庆模拟赛三总结
寄
90pts去死吧
还剩两个题不想搞了。
T1
只会打暴力/lb
暴力的话用前缀和 枚举一下就求出来了,正解还不知道。
暴力能拿70pts,挂了20pts/ll
官方题解用了STL,但是应该不需要。还有一种想法是记录下前缀和的位置和值,然后按权值小在前排序(注意位置从零开始排),然后再往后一遍循环更新答案,每次更新的时候还要判一下上一个len和val的贡献,感觉这种方法很多地方都有。
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=114514,M=1919810,inf=1145141919810;
ll Max(ll a,ll b){return a>=b?a:b;}
ll n,a[N];
struct xx{
ll val,id;
}sum[N];
ll ans1=inf,ans2=-1;
bool cmp(xx x,xx y){
return x.val==y.val?x.id>y.id:x.val<y.val;
}
int main(){
freopen("min.in","r",stdin);
freopen("min.out","w",stdout);
//ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i],sum[i].val=sum[i-1].val+a[i],sum[i].id=i;
sort(sum,sum+n+1,cmp); //很细节从零开始
ll last=inf,laslen=0;
for(int i=0;i<n;++i){
ll val=sum[i+1].val-sum[i].val;
ll len=abs(sum[i].id-sum[i+1].id);
if(ans1>val){
ans1=val;
ans2=len;
}
else if(ans1==val){
if(val==last&&val==0) len+=laslen;
ans2=max(ans2,len);
}
last=val;
laslen=len;
}
cout<<ans1<<'\n'<<ans2;
return 0;
}
T2
不会,赛时乱搞了10pts
先预处理出 个节点时二叉树的形态数目,,再预处理到 的前缀和。
然后去确定树的形态:先确定编号为n的树的节点个数,再去递归确定左右儿子,直到只有一个节点。
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=114514,M=1919810;
ll n,f[N],sum[N],root;
struct tree{
ll l,r,val;
}t[N];
void out(ll now){
if(now!=root) cout<<"(";
if(t[now].l) out(t[now].l);
cout<<"X";
if(t[now].r) out(t[now].r);
if(now!=root) cout<<")";
}
ll tot;
void build(ll &now,ll size,ll rk){
if(!size) return;
if(!now) now=++tot;
t[now].val=1;
if(size==1) return;
for(int i=0;i<size;++i)
if(rk>f[i]*f[size-i-1]) rk-=f[i]*f[size-i-1];
else{
ll ls=ceil((double)rk*1.0/f[size-i-1]);
build(t[now].l,i,ls),build(t[now].r,size-i-1,rk-f[size-i-1]*(ls-1));
return;
}
}
int main(){
cin>>n;
f[0]=1;
for(int i=1;i<=19;++i)
for(int j=0;j<i;++j)
f[i]+=f[j]*f[i-j-1];
for(int i=1;i<=19;++i) sum[i]=sum[i-1]+f[i];
ll size=lower_bound(sum+1,sum+20,n)-sum;
n-=sum[size-1];
build(root,size,n);
out(root);
return 0;
}
T3
推了一个很不靠谱的结论,估计宝玲。
骗了10pts,还有这事洛谷上的原题。link
T4
只会暴力/lb,真的不知道这种题怎么搞, 实现全局单点修改怎么搞啊???
頑張って