NOIP2018游记
凉夜竹堂虚,小睡匆匆醒。银漏无声月上阶,满地阑干影。何处最知秋,风在梧桐井。不惜骖鸾弄玉箫,露湿衣裳冷。
首先考试的时候心态有问题,考试前的目标大概是NOIP450+
最后却389分滚粗
D-inf
平时的学习不太认真,天赋也不是很好,NOIP信心不足啊。
D-1
考了一次NOIP信心赛,然后我就被卡常了,难道是NOIP爆炸的前兆。
D0
考试前一天机房颓废,然后和我一起颓废的小伙伴都考炸了,果然NOIP前不能颓废,不然就等死吧
考试前毒奶的数论,Tarjan都没考,难道NOIP不考Tarjan?
D1
T1 T2 200后,T3就没有太仔细去思考,直接敲了一发暴力就走人,考试结束后才发现自己的暴力和正解相差无几(方法一样),最后D1 255分滚粗走人,考完听大佬说T1原题?周围一群人T1AK,心态就炸了。
D2
T1,敲了1h都没有敲出来心态有点爆炸,最后在 1h30min时敲了出来,过了环的样例,最后却没有测试树的样例导致T1 40分,T2 推导了一波状压感觉有些困难果断看T3,发现T3可能是个倍增,然后开始敲,但是最后想崩了,敲了个暴力(44分)走人,开始看T2,感觉可做,但是有一种特殊情况没有考虑到,推到考试结束,最后只有50分。
两天下来 \(255+134=389\) 太低了,冬令营是没有希望了,只能好好准备省选了。
其实通过这次考试,我总结出了以下经验
① 考试不要紧张
② 要尽量写自己会做的所有分
③ 将以后的每场考试都当做正式考试对待
感觉快要退役了,先把BZOJ的题做一做,先把计算几何,各种数据结构,动态点分治,倍增,网络流,数论都学一学,冲刺以下明年的省选吧。
D1T1代码祭天
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
const int inf=1<<30;
int val[maxn];
int n;
inline int read()
{
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+(ch^'0'),ch=getchar();
return x;
}
int sum[maxn<<2],pos[maxn<<2];
int lazy[maxn<<2];
bool flag[maxn<<2];
inline void pushup(int rt)
{
if(sum[rt<<1]>sum[rt<<1|1])pos[rt]=pos[rt<<1|1],sum[rt]=sum[rt<<1|1];
else pos[rt]=pos[rt<<1],sum[rt]=sum[rt<<1];
flag[rt]=flag[rt<<1]|flag[rt<<1|1];
}
inline void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=val[l];
pos[rt]=l;
return ;
}
int mid=l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
inline void pushdown(int rt)
{
if(lazy[rt])
{
sum[rt<<1]+=lazy[rt];
sum[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void update(int L,int R,int l,int r,int rt,int v)
{
if(L<=l&&r<=R)
{
lazy[rt]+=v;
sum[rt]+=v;
return ;
}
int mid=l+r>>1;
pushdown(rt);
if(L<=mid)update(L,R,l,mid,rt<<1,v);
if(R>mid)update(L,R,mid+1,r,rt<<1|1,v);
pushup(rt);
}
void change(int poss,int l,int r,int rt)
{
if(l==r)
{
sum[rt]=inf;
flag[rt]=1;
return ;
}
int mid=l+r>>1;
pushdown(rt);
if(poss<=mid)change(poss,l,mid,rt<<1);
else change(poss,mid+1,r,rt<<1|1);
pushup(rt);
}
int check(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return flag[rt];
int mid=l+r>>1;
pushdown(rt);
int ans=0;
if(L<=mid)ans|=check(L,R,l,mid,rt<<1);
if(R>mid)ans|=check(L,R,mid+1,r,rt<<1|1);
return ans;
}
inline int queryl(int pos)
{
int l=1,r=pos,ans=pos;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid,pos,1,n,1)!=1)ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
inline int queryr(int pos)
{
int l=pos,r=n,ans=pos;
while(l<=r)
{
int mid=l+r>>1;
if(check(pos,mid,1,n,1)!=1)ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)val[i]=read();
long long ans=0;
int cnt=0;
build(1,n,1);
while(cnt<n)
{
int poss=pos[1],num=sum[1];
while(num==0)
{
cnt++;
change(poss,1,n,1);
poss=pos[1],num=sum[1];
}
if(cnt==n)break;
int l=queryl(poss),r=queryr(poss);
update(l,r,1,n,1,-num);
ans+=num;
}
printf("%lld\n",ans);
return 0;
}