[CF补题计划DAY4]Educational Codeforces Round 126 (Rated for Div. 2) A~D
2022.8.3 update:学会了线段树,更新D
碎碎念
昨天emo了又鸽了,后来发现心情不好只是因为忘记吃饭了,一顿夜宵解千愁
D怎么又是线段树啊,不活啦
不学线段树不行了呜呜
A.Array Balancing
第一发Wa了,考虑了后效性(?
实际根本不需要考虑,直接遍历判断,如果交换后a和b当前位与前一位的绝对值差的和更优则直接swap
后来想想把当前位与后一位的绝对值差考虑进去确实是假了,因为按照从左往右遍历的顺序,在考虑当前位时后一位是否会进行交换还不可知,贸然计算就会假。
B. Getting Zero
在校赛上做过类似的BFS,T了一发后发现有大量重复数据
单开一个ans数组记录已经知道的答案,如果输入的数字的答案已经可知,直接输出答案就行。
C. Water the Trees
首先可以确定树是不能长矮的,记mx为最高树高度,在最优地浇过水使所有树高度相同后,所有树的高度只可能是mx或mx+1。
如果是mx+2,就说明最高的树多浇了一个偶数天,相应的其他的树也要多浇一个偶数天,则不浇更优。
二分天数跑两遍,check函数里先判断至少需要奇数天的数量是否满足条件,再判断总需水量是否满足条件。
D. Progressions Covering
题意大概是给出一个b数组,每次操作选取长度为k的子段,使得
\(b[i]-=1,b[i+1]-=2,b[i+2]-=3...... b[i+k-1]-=k \ \ \ (i+k-1<=n)\)
问至少多少次可以使b的所有元素均小于等于0。
可以转化成维护一个差分序列,这样上述的操作就转化为区间\([i,i+k-1]\)每个数都减1,查询b的当前值转化为查询差分数组[1,i]的前缀和。
相对靠后的位置每次操作减去的值相对较大,因此可以从后往前考虑,判断这一位是否已经被减到小于等于0,若没有则执行区间减操作。
以前的我好懒啊怎么连代码都不贴……
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+100;
struct seg{
int l,r,sum;
int add;
}t[N*4];
int n,k,b[N];
inline void pushup(int p)
{
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
inline void build(int p,int l,int r)
{
t[p].l=l,t[p].r=r;
if(l==r){t[p].sum=b[r]-b[r-1];return;}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
inline void pushdown(int p)
{
if(t[p].add)
{
t[p<<1].sum+=t[p].add*(t[p<<1].r-t[p<<1].l+1);
t[p<<1|1].sum+=t[p].add*(t[p<<1|1].r-t[p<<1|1].l+1);
t[p<<1].add+=t[p].add;
t[p<<1|1].add+=t[p].add;
t[p].add=0;
}
}
inline void change(int p,int l,int r,int k)
{
if(l<=t[p].l&&r>=t[p].r)
{
t[p].sum+=k*(t[p].r-t[p].l+1);
t[p].add+=k;
return;
}
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(l<=mid) change(p<<1,l,r,k);
if(r>mid) change(p<<1|1,l,r,k);
pushup(p);
}
inline int ask(int p,int l,int r)
{
if(t[p].l>=l&&t[p].r<=r) {return t[p].sum;}
pushdown(p);
int mid=t[p].l+t[p].r>>1;
int val=0;
if(l<=mid) val+=ask(p<<1,l,r);
if(r>mid) val+=ask(p<<1|1,l,r);
return val;
}
main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>b[i];
int res=0;
build(1,1,n);
for(int i=n;i;i--)
{
int x=ask(1,1,i);
if(x<=0) continue;
int now=min(i,k);
int time=x/now+(x%now!=0);
res+=time;
change(1,i-now+1,i,-time);
}
cout<<res<<"\n";
}

浙公网安备 33010602011771号