題目大意:
給你一串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);
}
}
}
}