[BJOI2017]开车

[BJOI2017]开车 

直接做要用栈

修改?难以直接维护

统计边的贡献!

len*abs(pre)pre表示前缀car-stop

修改时候,整个区间的pre+1或者-1

分块,块内对pre排序并打标记

二分出0的位置,再根据pre的正负和本次是+1,-1,leni贡献+1还是-1的贡献

O(nsqrt(n)logn)

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}

namespace Miracle{
const int N=3*5e4+5;
const int B=450;
int n,m;
int L[N],R[N];
struct qs{
    int id,x;
}q[N];
int c[N],cnt;
int tot;
int pos[N],b[N];
int be[N],len[N];



vector<int>mem[B],sum[B];
int tag[B];
ll con[B];

int exi[N];//0: none 1:car -1:stop
int pre[N];
int buc[N];
bool cmp(int x,int y){
    return pre[x]<pre[y];
}
int li(int x){
    return lower_bound(c+1,c+cnt+1,x)-c;
}
int main(){
    rd(n);
    for(reg i=1;i<=n;++i) rd(pos[i]),c[++cnt]=pos[i];
    for(reg i=1;i<=n;++i) rd(b[i]),c[++cnt]=b[i];
    rd(m);
    for(reg i=1;i<=m;++i){
        rd(q[i].id);rd(q[i].x);
        c[++cnt]=q[i].x;
    }
    sort(c+1,c+cnt+1);
    cnt=unique(c+1,c+cnt+1)-c-1;
    
    int blo=sqrt(cnt)+1;
    for(reg i=1;i<=cnt;++i){
        be[i]=(i-1)/blo+1;
        if(!L[be[i]]) L[be[i]]=i;
        R[be[i]]=i;
        len[i]=c[i+1]-c[i];
    }
    len[cnt]=0;
    tot=be[cnt];
    
    for(reg i=1;i<=n;++i){
        int po=lower_bound(c+1,c+cnt+1,b[i])-c;
        --exi[po];
        po=lower_bound(c+1,c+cnt+1,pos[i])-c;
        ++exi[po];
    }
    ll ans=0;
    for(reg i=1;i<=cnt;++i){
        pre[i]=pre[i-1]+exi[i];
        ans+=(ll)len[i]*abs(pre[i]);
    }
    for(reg j=1;j<=tot;++j){
        tag[j]=0;
        for(reg i=L[j];i<=R[j];++i){
            mem[j].push_back(i);
            con[j]+=(ll)len[i]*abs(pre[i]);
        }
        sort(mem[j].begin(),mem[j].end(),cmp);
        sum[j].resize(mem[j].size());
        for(reg i=0;i<(int)mem[j].size();++i){
            sum[j][i]=len[mem[j][i]];
            if(i) sum[j][i]+=sum[j][i-1];
        }
    }
    printf("%lld\n",ans);
    for(reg o=1;o<=m;++o){
        int l=li(pos[q[o].id]),r=li(q[o].x);
        exi[l]--;exi[r]++;
        
        int c=-1;//l->r
        if(l>r) swap(l,r),c=1;//r->l
        --r;//warinig!!!
        if(be[l]==be[r]){        
            for(reg i=l;i<=r;++i) pre[i]+=c;
            ans-=con[be[l]];
            con[be[l]]=0;
            mem[be[l]].clear();
            sum[be[l]].clear();
            int j=be[l];
            for(reg i=L[be[l]];i<=R[be[l]];++i){
                pre[i]+=tag[be[l]];
                mem[j].push_back(i);
            }
            sort(mem[j].begin(),mem[j].end(),cmp);
            sum[j].resize(mem[j].size());
            for(reg i=0;i<(int)mem[j].size();++i){
                sum[j][i]=len[mem[j][i]];
                con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]);
                if(i) sum[j][i]+=sum[j][i-1];
            }
            tag[be[l]]=0;
            ans+=con[be[l]];
        }else{
            for(reg i=l;i<=R[be[l]];++i){
                pre[i]+=c;
            }
            int j=be[l];
            ans-=con[j];
            con[j]=0;
            mem[j].clear();
            sum[j].clear();
            for(reg i=L[j];i<=R[j];++i){
                pre[i]+=tag[j];
                mem[j].push_back(i);
            }
            sort(mem[j].begin(),mem[j].end(),cmp);
            sum[j].resize(mem[j].size());
            for(reg i=0;i<(int)mem[j].size();++i){
                sum[j][i]=len[mem[j][i]];
                con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]);
                if(i) sum[j][i]+=sum[j][i-1];
            }
            tag[j]=0;
            ans+=con[j];
        
            for(reg i=L[be[r]];i<=r;++i){
                pre[i]+=c;
            }
            j=be[r];
            ans-=con[j];
            con[j]=0;
            mem[j].clear();
            sum[j].clear();
            for(reg i=L[j];i<=R[j];++i){
                pre[i]+=tag[j];
                mem[j].push_back(i);
            }
            sort(mem[j].begin(),mem[j].end(),cmp);
            sum[j].resize(mem[j].size());
            for(reg i=0;i<(int)mem[j].size();++i){
                sum[j][i]=len[mem[j][i]];
                con[j]+=(ll)len[mem[j][i]]*abs(pre[mem[j][i]]);
                if(i) sum[j][i]+=sum[j][i-1];
            }
            tag[j]=0;
            ans+=con[j];
            
        
            for(reg j=be[l]+1;j<=be[r]-1;++j){
                pre[0]=-tag[j];
                if(c==-1){
                    int lp=upper_bound(mem[j].begin(),mem[j].end(),0,cmp)-mem[j].begin();
                    --lp;//warning!! maybe -1
                    if(lp!=-1){
                        ans+=(ll)sum[j][lp];
                        ans-=(ll)sum[j][mem[j].size()-1]-sum[j][lp];
                        con[j]+=(ll)sum[j][lp];
                        con[j]-=(ll)sum[j][mem[j].size()-1]-sum[j][lp];
                    }else{
                        ans-=(ll)sum[j][mem[j].size()-1];
                        con[j]-=(ll)sum[j][mem[j].size()-1];
                    }
                    
                }else{
                    int lp=lower_bound(mem[j].begin(),mem[j].end(),0,cmp)-mem[j].begin();
                    --lp;//warning!! maybe -1
                    if(lp!=-1){
                        ans-=(ll)sum[j][lp];
                        ans+=(ll)sum[j][mem[j].size()-1]-sum[j][lp];
                        con[j]-=(ll)sum[j][lp];
                        con[j]+=(ll)sum[j][mem[j].size()-1]-sum[j][lp];
                    }else{
                        ans+=(ll)sum[j][mem[j].size()-1];
                        con[j]+=(ll)sum[j][mem[j].size()-1];
                    }
                }
                tag[j]+=c;
            }
            pre[0]=0;
        }
        pos[q[o].id]=q[o].x;
        printf("%lld\n",ans);
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/4/11 10:31:35
*/
View Code

 

posted @ 2019-04-11 18:06  *Miracle*  阅读(315)  评论(0编辑  收藏  举报