zoukankan      html  css  js  c++  java
  • BZOJ2989 数列(二进制分组)

    这题其实可以cdq分治做,但是如果强制在线的话,这里有个牛逼方法叫二进制分组。

    它的基本思想是把修改操作按二进制分组,遇到修改就在尾部加一个,并与之前的合并,比如之前有23(16+4+2+1)个,加了一个后就变成了24(16+8)个,遇到查询就在每个组内查询,再加起来就好了。

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    #define M ((l+r)>>1)
    #define mk(a,b) make_pair(a,b)
    
    typedef pair<int,int> pr;
    const int N=60005,A=N+100000;
    char op[9];
    int n,q,x,y,tt,tp,a[N],rt[20][100005],rb[10000005],vs[10000005];
    vector<pr> v[20];
    struct nd {int l,r,s;}t[10000005];
    
    void ins2(int &x,int ls,int l,int r,int v) {
        t[x=rb[tt--]].s=t[ls].s+1,vs[x]=0;
        if(l==r) return;
        if(v<=M) t[x].r=t[ls].r,ins2(t[x].l,t[ls].l,l,M,v);
        else t[x].l=t[ls].l,ins2(t[x].r,t[ls].r,M+1,r,v);
    }
    int qr2(int x,int y,int l,int r,int L,int R) {
        if(L<=l&&R>=r) return t[x].s-t[y].s;
        if(R<=M) return qr2(t[x].l,t[y].l,l,M,L,R);
        if(L>M) return qr2(t[x].r,t[y].r,M+1,r,L,R);
        return qr2(t[x].l,t[y].l,l,M,L,R)+qr2(t[x].r,t[y].r,M+1,r,L,R);
    }
    void dl(int x,int l,int r) {
        if(vs[x]) return;
        rb[++tt]=x,vs[x]=1,dl(t[x].l,l,M),dl(t[x].r,M+1,r),t[x].s=t[x].l=t[x].r=0;
    }
    
    void ins(int x,int y) {
        v[++tp].push_back(mk(x,y)),ins2(rt[tp][1],rt[tp][0],1,A,y);
        while(tp>1&&v[tp-1].size()==v[tp].size()) {
            int t1=0,t2=0; vector<pr> t;
            for(int i=1;i<=v[tp-1].size();i++) dl(rt[tp-1][i],1,A);
            for(int i=1;i<=v[tp].size();i++) dl(rt[tp][i],1,A);
            while(t1<v[tp-1].size()||t2<v[tp].size()) {
                if(t1<v[tp-1].size()&&(t2==v[tp].size()||v[tp-1][t1]<v[tp][t2]))
                    t.push_back(v[tp-1][t1++]),ins2(rt[tp-1][t1+t2],rt[tp-1][t1+t2-1],1,A,v[tp-1][t1-1].second);
                else t.push_back(v[tp][t2++]),ins2(rt[tp-1][t1+t2],rt[tp-1][t1+t2-1],1,A,v[tp][t2-1].second);
            }
            v[tp-1]=t,v[tp].clear(),tp--;
        }
    }
    int qr(int x,int y,int k3) {
        int r=0;
        for(int i=1;i<=tp;i++) {
            int k=lower_bound(v[i].begin(),v[i].end(),mk(x+k3,0x3f3f3f3f))-v[i].begin();
            int k2=lower_bound(v[i].begin(),v[i].end(),mk(x-k3,0))-v[i].begin();
            r+=qr2(rt[i][k],rt[i][k2],1,A,max(1,y-k3),min(y+k3,A));
        }
        return r;
    }
    
    int main() {
        scanf("%d%d",&n,&q),vs[0]=1;
        for(int i=1;i<10000005;i++) rb[++tt]=i,vs[i]=1;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),ins(a[i]+i,a[i]-i+N);
        while(q--) {
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='Q') printf("%d
    ",qr(a[x]+x,a[x]-x+N,y));
            else a[x]=y,ins(y+x,y-x+N);
        }
        return 0;
    }
  • 相关阅读:
    arcgis10.2 sde配置
    创建只读账号oracle
    oracle 的tnsnames.ora,listener.ora
    gp工具的许可
    复制整个数据库
    显示二维表格的位置计算
    windows文件名格式的中文+数字混合字符串排序
    supergridcontrol记录,分页
    outlook-由于本机的限制,该操作已被取消。请与系统管理员联系。
    自定义单元格式
  • 原文地址:https://www.cnblogs.com/juruolty/p/6904480.html
Copyright © 2011-2022 走看看