题目大意:
给你一串b数组,数组中的数为1到n,顺序可能被打乱。a数组初始化为0,有两种操作
操作1:对于l r区间的a数组+1
操作2:查询l r之间的 ai/bi 向下取整。
解题思路:
这道题比赛卡了一下午,搞蒙了,很早的时候想出了维护最少需要升级经验的正解,但是和队友讨论感觉会T啊,因为有1这些数在,总感觉复杂度不对劲,后来想了一大堆其他做法也没做出来,然后又转回去写第一种想法,写到一半的时候自认为想出了一种更简单的写法,写了以后T了,然后就这样了= = 就没再管第一种写法。。。结果赛后写了以后AC。。。
惨淡2题收尾。
我们认为一个数升级所需的经验就是他们自己的大小,升级代表当前res++。
其实就是维护区间升级所需的最少经验值,当这个值为负数的时候就需要更新到子节点去将答案更新。
这个复杂度真的不会证啊,莫名其妙就过了= =
要是早知道也不会卡5个消失了 。。。
Ac代码:
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn=1e5+5;
const int INF=1e9+7;
int n,m,ans,a[maxn];
char s[100];
struct node
{
int l,r,mid,val; //val升级所需经验 sum当前区间获得经验 res当前答案总和
int sum,res;
}t[maxn<<2];
void pushup(int rt) //val取最小值
{
t[rt].res=t[lson].res+t[rson].res;
t[rt].val=min(t[lson].val,t[rson].val);
}
void pushdown(int rt) //val记得更新
{
if(t[rt].sum)
{
t[lson].sum+=t[rt].sum;
t[lson].val-=t[rt].sum;
t[rson].sum+=t[rt].sum;
t[rson].val-=t[rt].sum;
t[rt].sum=0;
return ;
}
}
void build(int l,int r,int rt)
{
int mid=(l+r)>>1;
t[rt].l=l,t[rt].r=r,t[rt].mid=mid;
t[rt].val=t[rt].sum=t[rt].res=0;
if(l==r)
{
t[rt].val=a[l]; //默认升级经验为自己的大小
return ;
}
build(l,mid,lson);
build(mid+1,r,rson);
pushup(rt);
}
void update(int l,int r,int rt)
{
if(l<=t[rt].l&&t[rt].r<=r)
{
t[rt].sum++; //更新val 和 sum
t[rt].val--;
return ;
}
pushdown(rt);
if(l<=t[rt].mid) update(l,r,lson);
if(r>t[rt].mid) update(l,r,rson);
pushup(rt);
}
void query(int l,int r,int rt)
{
if(l<=t[rt].l&&t[rt].r<=r&&t[rt].val>0) //表示当前区间没有需要更新的
{
ans+=t[rt].res;
return;
}
if(t[rt].l==t[rt].r) //更新到叶子结点
{
if(t[rt].val<=0)
{
t[rt].val+=t[rt].sum; //将val还原
t[rt].res++; //答案++
t[rt].sum-=t[rt].val; //sum减去val
t[rt].res+=t[rt].sum/a[t[rt].r]; //处理出新的res以及val
t[rt].val=a[t[rt].r]-t[rt].sum%a[t[rt].r];
t[rt].sum=0;
}
ans+=t[rt].res;
return ;
}
pushdown(rt);
if(l<=t[rt].mid)query(l,r,lson);
if(r>t[rt].mid)query(l,r,rson);
pushup(rt);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,n,1);
while(m--)
{
int l,r;
scanf("%s%d%d",s,&l,&r);
if(s[0]=='a')update(l,r,1);
else
{
ans=0;
query(l,r,1);
printf("%d\n",ans);
}
}
}
}