zoukankan      html  css  js  c++  java
  • [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('
    ');}
    
    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
    ",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
    ",ans);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/4/11 10:31:35
    */
    View Code
  • 相关阅读:
    js 实现商品放大镜效果
    Angular.js数据绑定时自动转义html标签及内容
    Sublime 快捷键一览表
    这么牛的简历,你见过么?
    正向代理与反向代理
    负载均衡
    redis搭建与安装
    svn服务配置和日常维护命令
    Mysql导出导入
    linux搭建svn服务器
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10691399.html
Copyright © 2011-2022 走看看