Solution to a problem P3863 [sequence]

If only one number, it seems well maintained.

Maintain the value of every moment of this number plus. Query a certain period of time greater than the number of times a certain value. The block of time can be done.

But if it is \ (n \) the number of it? If you do online, it does not seem well maintained. So off down to inquire about ordering, order processing just fine.

Then how does it modify the processing window? If observed in \ (T \) time to \ ([l, r] \ ) plus \ (V \) , the processing will \ ([l, r] \ ) are the same impact upon each number . Therefore, a modification operation each divided into two parts:

  • The first portion, in the process of \ (L \) when the number of time \ ([t, m] \ ) are plus \ (V \) .
  • The second part, in the process of \ (r + 1 \) when the number of time \ ([t, m] \ ) was subtracted \ (V \) , to offset the impact (since this operation will not \ (R & lt +1 \) number and after the impact, it is subtracted).

(Is not it feel a bit like scanning line on the road)

So that we can get the value of each number is added each time the.

Treatment (I \) \ number of \ (T \) when the second inquiry, inquiry block \ ([0, t-1 ] \) how many time greater than or equal \ (y - a_i \) can.

Noting that the final output is output according to the input order, we had to deal with inquiries about the order.

# include <bits/stdc++.h>
# define rr register
# define int long long
const int N=100010;
struct Line{//修改
    int x;
    int Time;
    int v;
}a[N<<1];
struct Asker{//查询
    int x,v; 
    int Time;
    int Index;// 记录是第几次询问
}ask[N];
int cnta,cntb;//修改数量 & 查询数量
int ans[N]; // 存储每一次询问的答案
int val[N];
int n,m;
/* 分块部分 */
int tseque[N];
int fseque[N];
int add[N];
int Kuai[N];
int KL[N],KR[N];
/* 分块部分 */
int siz;// 要分的块大小
inline int read(void){
    int res,f=1;
    char c;
    while((c=getchar())<'0'||c>'9')
        if(c=='-')f=-1;
    res=c-48;
    while((c=getchar())>='0'&&c<='9')   
        res=res*10+c-48;
    return res*f;       
}
inline bool cmp_Line(Line X,Line Y){//给修改排序
    return X.x!=Y.x?X.x<Y.x:X.Time<Y.Time;
}
inline bool cmp_Ask(Asker X,Asker Y){//给询问排序
    return X.x!=Y.x?X.x<Y.x:X.Time<Y.Time;
}
inline bool cmp_Integer(int X,int Y){//为了给块内元素从大到小排序用的
    return X>Y;
}
inline void resort(int x){//每次修改之后,块内元素需要重新排序
    for(rr int i=KL[x];i<=KR[x];++i)
        fseque[i]=tseque[i];
    std::sort(fseque+KL[x],fseque+KR[x]+1,cmp_Integer);
    return; 
}
inline void change(int l,int r,int v){// 分块修改操作
    l=std::max(l,0ll);
    r=std::min(r,m);
    if(Kuai[l]==Kuai[r]){
        for(rr int i=l;i<=r;++i){
            tseque[i]+=v;
        }
        resort(Kuai[l]);
        return;
    }
    for(rr int i=l;i<=KR[Kuai[l]];++i)
        tseque[i]+=v;
    resort(Kuai[l]);
    for(rr int i=r;i>=KL[Kuai[r]];--i)
        tseque[i]+=v;
    resort(Kuai[r]);
    for(rr int i=Kuai[l]+1;i<=Kuai[r]-1;++i){
        add[i]+=v;
    }
    return;
}
inline int query(int l,int r,int v){// 分块查询操作
    int cnt=0;
    if(Kuai[l]==Kuai[r]){
        for(rr int i=l;i<=r;++i)
            if(tseque[i]+add[Kuai[i]]>=v)
                ++cnt;
        return cnt;     
    }
    for(rr int i=l;i<=KR[Kuai[l]];++i)
        if(tseque[i]+add[Kuai[i]]>=v)
            ++cnt;
    for(rr int i=r;i>=KL[Kuai[r]];--i)
        if(tseque[i]+add[Kuai[i]]>=v)
            ++cnt;
    for(rr int i=Kuai[l]+1;i<=Kuai[r]-1;++i){
        int L=KL[i],R=KR[i],ans=KL[i]-1;
        while(L<=R){
            int mid=(L+R)>>1;
            if(fseque[mid]+add[Kuai[mid]]>=v){
                ans=mid;
                L=mid+1;
            }else{
                R=mid-1;
            }
        }
        cnt+=(ans-KL[i])+1;
    }
    return cnt;
}
# undef int
int main(void){
# define int long long
    n=read(),m=read();
    for(rr int i=1;i<=n;++i){
        val[i]=read();
    }
    for(rr int i=1,opt;i<=m;++i){
        opt=read();
        if(opt==1){
            int l=read(),r=read(),v=read();
            a[++cnta].x=l;
            a[cnta].Time=i;
            a[cnta].v=v;
            a[++cnta].x=r+1;
            a[cnta].Time=i;
            a[cnta].v=-v;
        }else{
            int p=read(),y=read();
            ask[++cntb].x=p;
            ask[cntb].Index=cntb;
            ask[cntb].v=y;
            ask[cntb].Time=i;
        }
    }
    std::sort(a+1,a+1+cnta,cmp_Line);
    std::sort(ask+1,ask+1+cntb,cmp_Ask);// 读入、存储并排序每一个操作
    siz=sqrt(m);
    for(rr int i=0;i<=m;++i){
        Kuai[i]=i/siz+1;
    }
    for(rr int i=1;(i-1)*siz<=m;++i){
        KL[i]=(i-1)*siz;
        KR[i]=std::min(i*siz-1,m);
    }
    int now=1;
    for(rr int i=1;i<=cntb;++i){
        while((a[now].x<ask[i].x||(a[now].x==ask[i].x&&a[now].Time<ask[i].Time))&&now<=cnta){
            change(a[now].Time,m,a[now].v);
            ++now;
        }
        ans[ask[i].Index]=query(0,ask[i].Time-1,ask[i].v-val[ask[i].x]);
    }
    for(rr int i=1;i<=cntb;++i)
        printf("%lld\n",ans[i]);
    return 0;
} 

Guess you like

Origin www.cnblogs.com/liuzongxin/p/11949273.html