CodeForces 551E(平方分割

题意:给出一个数列,要求支持以下两种操作,1)给某区间内的所有数都加上x,2)输出数列中等于y的两个数的最大距离。

比赛的时候没想到这是分块(花式暴力。。),以为是线段书啥的,然后不会。。赛后听说是分块,其实思路一下就想到了(以前照书抄过一个分块题)。。。。然而第一次写的时候脑残完全写错了,发现的时候汗啊。。全删了重写,又写了一个小时左右,wa了两次,修正了两个bug,过了。。。分成若干块,如果改变的区间完全包含一个块,那就直接给总的val加x,不完全包含就o(n)直接处理,查询的时候是二分,其实这个题还是比较简单的分块,因为查询没有区间问题,就是从头到尾,否则查询也比较麻烦。

#include<iostream>

#include<map>

#include<algorithm>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<vector>

#include<queue>

#include<stack>

#include<functional>

#define pb push_back

using namespace std;

typedef long long ll;

const int maxv=5e5+40;

const int sz=1000;

struct Num{

    ll o,v;

    bool operator < (const Num &C)const{

        if(v!=C.v) return v<C.v;

        else return o<C.o;

    }

};

vector<Num> bucket[1000];

ll a[maxv];

ll val[maxv];

int n,q;

void update(int l,int r,ll x){

    if(l/sz==r/sz){

        for(int i=l;i<=r;i++) a[i]+=x;

        bucket[l/sz].clear();

        for(int i=l/sz*sz;i<l/sz*sz+sz;i++) bucket[l/sz].pb((Num){i,a[i]});

        sort(bucket[l/sz].begin(),bucket[l/sz].end());

    }else{

        for(int i=l/sz+1;i<r/sz;i++) val[i]+=x;

        update(l,l/sz*sz+sz-1,x);

        update(r/sz*sz,r,x);

    }

    return;

}

bool cmp(Num a,Num b){

    return a.v<b.v;

}

int quaryl(ll y){

    for(int i=0;i<=n/sz;i++){

        Num tar;

        tar.v=y-val[i];

        vector<Num>::iterator it=lower_bound(bucket[i].begin(),bucket[i].end(),tar,cmp);

        if(it!=bucket[i].end()&&(*it).v==tar.v){

            return (*it).o;

        }

    }

    return -1;

}

int queryr(ll y){

    for(int i=n/sz;i>=0;i--){

        Num tar;

        tar.v=y-val[i];

        vector<Num>::iterator it=upper_bound(bucket[i].begin(),bucket[i].end(),tar,cmp);

        if(it!=bucket[i].begin()&&(*(it-1)).v==tar.v){

            return (*(it-1)).o;

        }

    }

    return -1;

}

int main(){

    ////freopen("/home/files/CppFiles/in","r",stdin);

    cin>>n>>q;

    for(int i=0;i<n;i++){

        scanf("%I64d",&a[i]);

        bucket[i/sz].pb((Num){i,a[i]});

    }

    for(int i=0;i<=n/sz;i++) sort(bucket[i].begin(),bucket[i].end());

    while(q--){

        int type;

        scanf("%d",&type);

        if(type==1){

            int l,r,x;

            scanf("%d%d%d",&l,&r,&x);

            update(l-1,r-1,x);

        }else{

            int y;

            scanf("%d",&y);

            int l=quaryl(y);

            if(l!=-1){

                printf("%d\n",queryr(y)-l);

            }else{

                puts("-1");

            }

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(codeforces)