• P3374 【模板】树状数组 1(cdq)


    P3374 【模板】树状数组 1

    cdq分治

    刚学了cdq分治(dyf神犇强力安利下),发现可以做这种题,当然是来试水了(逃

    cdq好像只能离线的样子

    cdq分治(转)

    以下是摘录的几句:

    • 在合并的时候,我们只处理左区间的修改,只统计右区间的查询 
      因为左区间的修改一定可以影响右区间的查询 
      这就体现出了CDQ分治的基本思想了
    • 我们把所有操作都记录到了一个数组中,所以数组的大小至少要开到500000*3

    过程: 按操作顺序读入--->按位置从小到大归并排序(这样可以保证每个询问操作进行前,都只有位置更前的修改操作被执行)--->(蓝后就没了)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    using namespace std;
    template <typename T> inline void read(T &x){
        char c=getchar(); x=0; bool f=1;
        while(!isdigit(c)) f= !f||c=='-' ? 0:1,c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
        x= f? x:-x;
    }
    int wt[50];
    template <typename T> inline void output(T x){
        if(!x) {putchar(48); return;}
        if(x<0) putchar('-'),x=-x;
        int l=0;
        while(x) wt[++l]=x%10,x/=10;
        while(l) putchar(wt[l--]+48);
    } 
    //-----可无视------
    struct data{ int id,v,opt; //id:操作所在位,v:视情况而定 opt:操作 bool operator < (const data &tmp) const{ return id<tmp.id||(id==tmp.id&&opt<tmp.opt); //①位置从小到大,②操作先修改后查询 } }a[1500002],b[1500002]; //注意开3倍 int n,m,cnt,tot,ans[500002]; //cnt:操作数 tot:询问数 inline void cdq(int l,int r){ //cdq分治(差不多就是归并排序了) if(l==r) return ; int mid=l+((r-l)>>1); cdq(l,mid); cdq(mid+1,r); int t1=l,t2=mid+1,sum=0; for(int i=l;i<=r;++i){ if((t1<=mid&&a[t1]<a[t2])||t2>r){ if(a[t1].opt==1) sum+=a[t1].v; b[i]=a[t1++]; }else{ if(a[t2].opt==2) ans[a[t2].v]-=sum; else if(a[t2].opt==3) ans[a[t2].v]+=sum; b[i]=a[t2++]; } } for(int i=l;i<=r;++i) a[i]=b[i]; } int main(){ read(n); read(m); int q1,q2; for(int i=1;i<=n;++i) read(a[++cnt].v),a[cnt].id=i,a[cnt].opt=1; //把初始序列当成修改操作 for(int i=1;i<=m;++i){ read(a[++cnt].opt); read(q1); read(q2); if(a[cnt].opt==1) a[cnt].id=q1,a[cnt].v=q2; else{ //查询分为2个操作:左端点减前缀和,右端点加前缀和 a[cnt].id=q1-1; a[cnt].v=++tot; //左端点操作 a[++cnt].id=q2; a[cnt].v=tot; a[cnt].opt=3; //右端点 } } cdq(1,cnt); for(int i=1;i<=tot;++i) output(ans[i]),putchar(' '); return 0; }
  • 相关阅读:
    java9
    java8
    java7
    JavaScript将字符串拆分为数组
    JavaScript return false
    Java中前台往后台传多个id参数
    Easyui清除tree的选中
    jquery easyui tree的全选与反选
    android源码开发基础知识了解
    Android activity的生命周期
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9657264.html
Copyright © 2020-2023  润新知