题目: 传送门
题意: Ailce 有n根头发,每根头发长度为ai,头发可能会增长,如果头发长度大于l就需要被剪,询问如果Ailce去剪头发,需要多久(规定剪一次需要1s,并且如果很多需要剪的头发相邻,可以一次都剪掉)。
题目: 刚拿到题目的时候想的很复杂,本来打算用线段树做的,但是后来仔细想想其实并没有这么难.
题目中说明了剪头发只是想象出来的,即头发长度没有被剪掉,只是询问现在如果去剪头发需要的时间。所以在题目中头发的长度只会不断增长而不会减少.
我们可以先分情况讨论可能出现的可能,如果该根头发是要剪的,所以它再增长的话是不会对所剪的次数造成影响的.如果该头发起初不要剪,增长了之后要剪,我们需要讨论与它相邻的头发的状态,如果只有一边的头发需要剪,则不会造成影响,如果两边都是要剪的头发,则说明把两部分需要剪的头发连了起来,所以要剪的次数就会-1,如果都不要剪,则这根头发要单独再剪一次,结果增加.
AC代码:
long long a[100100];
int main() {
long long now = 0;//表示当前需要剪的次数
long long n,m,l;
cin>>n>>m>>l;
for(int i = 0;i<n;i++) {
cin>>a[i];
if(a[i]>l) {
if(i==0) {
now++;
}
else {
if(a[i-1]<=l) now++; //如果前一个不需要剪,则次数要增加
}
}
}
while(m--) {
int cmp;
cin>>cmp;
if(cmp==0) {
cout<<now<<endl;
}
else {
int p,d;
cin>>p>>d;
p-=1;//题目是从1计数,而我是从0计数。
if(a[p]>l) continue;//如果本身大于就不会影响
a[p] +=d;
if(a[p]<=l) continue;//如果增长了之后还是小于也不会影响
if(p!=0) {//防止越界
if(p==n-1) {
if(a[p-1]<=l) now++;
}
else {
if(a[p-1]>l&&a[p+1]>l) now--;//左右两边都要剪结果减小
else if(a[p-1]<=l&&a[p+1]<=l) now++;//左右两边都不要剪则结果增加
}
}
else {
if(a[p+1]<=l) now++;
}
}
}
return 0;
}