[Block] entry block

summary

The first few are used to understand the thoughts and exercises can block the tree line or with a pair of tree line like lch said first consider the advantages of various data structures as much as possible with the most simple of the most appropriate

 

A single adder block Point Query Interval

Gives a long series of n, and n operation, the operation involving the addition interval, a single enumeration value

Adding to each block a set flag, each operation (1) marking each block O directly, without the entire block is relatively small due to the elements, modify the value of the element of violence.

Each element returned challenge value when they are in addition flag adding block

Such is the complexity of the operation each time O (n / m) + O (m), based on a mean inequality, when m is the minimum overall complexity √n

You can draw a picture interval more intuitive QAQ

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
const int N=5e4+5inf=0x3f3f3f3f;
int n,base,a[N],bl[N],addtg[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void add(int l,int r,int c){
    for(int i=l;i<=(Min(r,bl[l]*base));++i) a[i]+=c;
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1;i<=r;++i) a[i]+=c;
    for(int i=bl[l]+1;i<=bl[r]-1;++i) addtg[i]+=c;
}

int main(){
//    freopen("in.txt","r",stdin);
    rd(n),base=sqrt(n);
    for(int i=1;i<=n;++i) rd(a[i]);
    for(int i=1;i<=n;++i) bl[i]=(i-1)/base+1;
    for(int i=1,op,l,r,c;i<=n;++i){
        rd(op),rd(l),rd(r),rd(c);
        if(!op) add(l,r,c);
        else printf("%d\n",a[r]+addtg[bl[r]]);
    }
    return 0;
}

 

Small number of elements within a certain number interval adder block two interrogation interval

A given length of the number of columns n, and n operation, the operation involving the addition interval, interrogation is smaller than a value x is the number of elements within the interval.

For each interval operation:

1. incomplete block  O of (√n) elements of how to deal with?

2.O (√n) a  piece of  how to deal with?

3. To what pre-information (no more than the complexity of the operation back)?

To think first and only case of the operation of inquiry, incomplete statistics can block enumeration; and to look for a value less than the number of elements in each piece, so we had to ask within the block elements are ordered, so Functional dichotomy of the block query when required to do it again pre-sorting, the complexity of O (nlogn), each half of each query, and violence 2√n elements within block √n, the total complexity of O ( nlogn + n√nlog√n).

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
const int N=5e4+5,M=500+5,inf=0x3f3f3f3f;
int n,base,a[N],bl[N],addtg[N];
vector<int>vec[M];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void reset(int x){
    vec[x].clear();
    for(int i=(x-1)*base+1;i<=(Min(x*base,n));++i)
    vec[x].push_back(a[i]);
    sort(vec[x].begin(),vec[x].end());
}
void add(int l,int r,int k){
    for(int i=l;i<=(Min(r,bl[l]*base));++i) a[i]+=k;
    reset(bl[l]);
    if(bl[l]!=bl[r]){
        for(int i=(bl[r]-1)*base+1;i<=r;++i) a[i]+=k;
        reset(bl[r]);
    }
    for(int i=bl[l]+1;i<=bl[r]-1;++i) addtg[i]+=k;
}

int query(int l,int r,int k){
    int ans=0;
    for(int i=l;i<=(Min(r,bl[l]*base));++i)
    if(a[i]+addtg[bl[i]]<k) ++ans;
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1;i<=r;++i)
    if(a[i]+addtg[bl[i]]<k) ++ans;
    for(int i=bl[l]+1,x;i<=bl[r]-1;++i){
        x=k-addtg[i];
        ans+=lower_bound(vec[i].begin(),vec[i].end(),x)-vec[i].begin();
    }
    return ans;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),base=sqrt(n);
    for(int i=1;i<=n;++i)
    rd(a[i]),bl[i]=(i-1)/base+1,vec[bl[i]].push_back(a[i]);
    for(int i=1;i<=bl[n];++i)
    sort(vec[i].begin(),vec[i].end());
    for(int i=1,op,l,r,k;i<=n;++i){
        rd(op),rd(l),rd(r),rd(k);
        if(!op) add(l,r,k);
        else printf("%d\n",query(l,r,k*k));
    }
    return 0;
}

 

Block segments in addition interrogation precursor

A given length of n columns, and n operations, the operation involving the addition interval, interrogation interval less than a certain value x prodromal (smaller than the largest element

Then a second solution of the problem, in fact, slightly modified as long as half of the query within the block.

But this title really want to express: the block can be maintained within other structures to make it more scalability, such as a release  the SET  , so that if there is insertion, deletion of elements, will be more convenient.

Debugging techniques to detect sub-blocks:

May generate a large number of data, and then with two different block sizes beat code pair, you may also try to adjust the block size of the operating time constant decreases.

The title base = √n much slower than 1000

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
const int N=1e5+5,M=1000+5,inf=0x3f3f3f3f;
int n,base,a[N],bl[N],addtg[N];
set<int>s[M];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void add(int l,int r,int k){
    for(int i=l;i<=(Min(r,bl[l]*base));++i){
        s[bl[i]].erase(a[i]);
        a[i]+=k;
        s[bl[i]].insert(a[i]);
    }
    if(bl[l]!=bl[r]){
        for(int i=(bl[r]-1)*base+1;i<=r;++i){
            s[bl[i]].erase(a[i]);
            a[i]+=k;
            s[bl[i]].insert(a[i]);
        }
    }
    for(int i=bl[l]+1;i<=bl[r]-1;++i) addtg[i]+=k;
}

int query(int l,int r,int k){
    int ans=-1;
    for(int i=l,x;i<=(Min(r,bl[l]*base));++i){
        x=a[i]+addtg[bl[i]];
        if(x<k) ans=Max(ans,x);
    }
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1,x;i<=r;++i){
        x=a[i]+addtg[bl[i]];
        if(x<k) ans=Max(ans,x);
    }
    for(int i=bl[l]+1,x;i<=bl[r]-1;++i){
        x=k-addtg[i];
        set<int>::iterator iter=s[i].lower_bound(x);
        if(iter==s[i].begin()) continue;
        --iter;
        ans=Max(ans,*iter+addtg[i]);
    }
    return ans;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),base=1000;
    for(int i=1;i<=n;++i)
    rd(a[i]),bl[i]=(i-1)/base+1,s[bl[i]].insert(a[i]);
    for(int i=1,op,l,r,k;i<=n;++i){
        rd(op),rd(l),rd(r),rd(k);
        if(!op) add(l,r,k);
        else printf("%d\n",query(l,r,k));
    }
    return 0;
}

Block & interval plus four summation interval

A given length of the number of columns n, and n operation, the operation involving the addition interval, the summation interval

 

And in order to quickly complete the answer statistics blocks, each block elements need to maintain and, first pretreatment it.

 

Modifying operation of interval, a direct change the incomplete block, the update block elements and the way; tag before complete block similar approach, and the element directly from the values ​​of the increment calculation block elements and the applied.

 

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
const int N=5e4+5,M=500+5,inf=0x3f3f3f3f,P=9999973;
int n,base,bl[N];
ll a[N],sum[N],addtg[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void add(int l,int r,ll k){
    for(int i=l;i<=(Min(r,bl[l]*base));++i) a[i]+=k,sum[bl[i]]+=k;
    if(bl[l]!=bl[r])
        for(int i=(bl[r]-1)*base+1;i<=r;++i) a[i]+=k,sum[bl[i]]+=k;
    for(int i=bl[l]+1;i<=bl[r]-1;++i) addtg[i]+=k;
}

ll query(int l,int r,ll k){
    ll ans=0;
    for(int i=l;i<=(Min(r,bl[l]*base));++i) ans=(ans+a[i]+addtg[bl[i]])%k;
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1;i<=r;++i) ans=(ans+a[i]+addtg[bl[i]])%k;
    for(int i=bl[l]+1;i<=bl[r]-1;++i)
    ans=(ans+sum[i]+addtg[i]*base)%k;
    return ans;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),base=sqrt(n);
    for(int i=1;i<=n;++i)
    rd(a[i]),bl[i]=(i-1)/base+1,sum[bl[i]]+=a[i];
    for(int i=1,op,l,r,k;i<=n;++i){
        rd(op),rd(l),rd(r),rd(k);
        if(!op) add(l,r,k);
        else printf("%lld\n",query(l,r,k+1)%(k+1));
    }
    return 0;
}

Block & section prescribing five summation interval

And tree line to do this problem thinking almost have to maintain a current interval if all 0/1

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
const int N=5e4+5,M=500+5,inf=0x3f3f3f3f,P=9999973;
int n,base,bl[N];
ll a[N],sum[N],addtg[N],tg[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void updat(int x){
    if(tg[x]) return;
    tg[x]=1,sum[x]=0;
    for(int i=(x-1)*base+1;i<=x*base;++i){
        a[i]=sqrt(a[i]),sum[x]+=a[i];
        if(a[i]>1) tg[x]=0;
    }
}
void sqr(int l,int r){
    for(int i=l;i<=(Min(r,bl[l]*base));++i){
        sum[bl[i]]-=a[i];
        a[i]=sqrt(a[i]);
        sum[bl[i]]+=a[i];
    }
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1;i<=r;++i){
        sum[bl[i]]-=a[i];
        a[i]=sqrt(a[i]);
        sum[bl[i]]+=a[i];
    }
    for(int i=bl[l]+1;i<=bl[r]-1;++i) updat(i);
}

ll query(int l,int r){
    ll ans=0;
    for(int i=l;i<=(Min(r,bl[l]*base));++i) ans+=a[i];
    if(bl[l]!=bl[r])
    for(int i=(bl[r]-1)*base+1;i<=r;++i) ans+=a[i];
    for(int i=bl[l]+1;i<=bl[r]-1;++i) ans+=sum[i];
    return ans;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),base=sqrt(n);
    for(int i=1;i<=n;++i)
    rd(a[i]),bl[i]=(i-1)/base+1,sum[bl[i]]+=a[i];
    for(int i=1,op,l,r,k;i<=n;++i){
        rd(op),rd(l),rd(r),rd(k);
        if(!op) sqr(l,r);
        else printf("%lld\n",query(l,r));
    }
    return 0;
}

Block & six à insertion à query

A given length of the number of columns n, and n operation, the operation involves a single point of insertion, a single point of inquiry, randomly generated data.

This problem can be put in each block of a dynamic array, first find the location of each time block is inserted, and then insert the violence, the other elements in the block directly to a backward movement, of course, also possible to use a linked list.

If the first block in a large number of single point of insertion, the size of the block will be much higher than √N, no piece of violence in the complexity of the need to introduce a further ensure the following: re-partition (reconstructed)

After inserting each number n times, the number of columns again at block average, the reconstruction was required complexity O (n), the number of √N reconstructed, reconstructed so that no problem complexity, and to ensure that each block size is relatively balanced. Of course, it can be reconstructed when a block is too large, or only to the block in half.

Not fully understand the code so the first fold

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
#define Abs(x) (x)<0?-x:x;
#define rg register
const int N=1e5+5,M=1000+5,inf=0x3f3f3f3f,P=9999973;
int n,m,base,a[N],st[N],top;
vector<int>v[M];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

pair<int,int>query(int pos){
    int x=1;
    while(pos>v[x].size()) pos-=v[x].size(),++x;
    return make_pair(x,pos-1);
}

void rebuild(){
    top=0;
    for(int i=1;i<=m;++i){
        for(vector<int>::iterator j=v[i].begin();j!=v[i].end();++j) st[++top]=*j;
        v[i].clear();
    }
    int base2=sqrt(top);
    for(int i=1;i<=top;++i) v[(i-1)/base2+1].push_back(st[i]);
    m=(top-1)/base2+1;
}

void insert(int pos,int x){
    pair<int,int> t=query(pos);
    v[t.first].insert(v[t.first].begin()+t.second,x);
    if(v[t.first].size()>base*20) rebuild();
}


int main(){
    freopen("in.txt","r",stdin);
    rd(n),base=sqrt(n),m=(n-1)/base+1;
    for(int i=1;i<=n;++i) rd(a[i]),v[(i-1)/base+1].push_back(a[i]);
    for(int i=1,op,l,r,k;i<=n;++i){
        rd(op),rd(l),rd(r),rd(k);
        if(!op) insert(l,r);
        else{
            pair<int,int> t=query(r);
            printf("%d\n",v[t.first][t.second]);
        }
    }
    return 0;
}
View Code

 

 

Guess you like

Origin www.cnblogs.com/lxyyyy/p/11271333.html