CodeForces 551E 分块

 

题目链接:http://codeforces.com/problemset/problem/551/E

题意:给定一个长度为N的序列。 有2个操作 1 l r v:序列第l项到第r项加v(区间加),  2 v:求整个序列中值为v的数的位置的差值最大是多少。不存在输出-1.

思路:分块。 每块维护该块序列排序后的序列。 对于区间修改,我们定义一个lazy标记。对于整块的修改我们只修改lazy, 其他情况暴力修改。然后情况该块后重新加入修改后的块然后排序。 对于查询操作。查询每块时v应该减去该块的lazy值。 然后2分查即可。

 

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>  
#include<string.h>  
#include<cstring>
#include<algorithm>  
#include<queue>  
#include<math.h>  
#include<time.h>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
typedef long long int LL;
const int MAXN = 5*100000 + 10;
int belong[MAXN], block, num, L[MAXN], R[MAXN];
int n, q;
LL val[MAXN], lazy[MAXN];
struct Node{
    LL v;
    int id;
    Node(LL _v, int _id) :v(_v), id(_id){};
    bool operator < (const Node &a)const{
        return v==a.v?id<a.id:v<a.v;
    }
};
vector<Node>Bval[MAXN];
void build(){
    block = (int)sqrt(n+0.5);
    num = n / block; if (n%block){ num++; }
    for (int i = 1; i <= num; i++){
        lazy[i] = 0; Bval[i].clear();
        L[i] = (i - 1)*block + 1; R[i] = i*block;
    }
    R[num] = n;
    for (int i = 1; i <= n; i++){
        belong[i] = ((i - 1) / block) + 1;
    }
    for (int i = 1; i <= num; i++){
        for (int k = L[i]; k <= R[i]; k++){
            Bval[i].push_back(Node(val[k],k));
        }
        sort(Bval[i].begin(), Bval[i].end());
    }
}
void modify(int st,int ed, LL v){
    if (belong[st] == belong[ed]){
        for (int i = st; i <= ed; i++){
            val[i] += v;
        }
        Bval[belong[st]].clear();
        for (int i = L[belong[st]]; i <= R[belong[st]]; i++){
            Bval[belong[st]].push_back(Node(val[i], i));
        }
        sort(Bval[belong[st]].begin(), Bval[belong[st]].end());
        return;
    }
    for (int i = st; i <= R[belong[st]]; i++){
        val[i] += v;
    }
    Bval[belong[st]].clear();
    for (int i = L[belong[st]]; i <= R[belong[st]]; i++){
        Bval[belong[st]].push_back(Node(val[i], i));
    }
    sort(Bval[belong[st]].begin(), Bval[belong[st]].end());
    for (int i = belong[st] + 1; i < belong[ed]; i++){
        lazy[i] += v;
    }
    for (int i = L[belong[ed]]; i <= ed; i++){
        val[i] += v;
    }
    Bval[belong[ed]].clear();
    for (int i = L[belong[ed]]; i <= R[belong[ed]]; i++){
        Bval[belong[ed]].push_back(Node(val[i], i));
    }
    sort(Bval[belong[ed]].begin(), Bval[belong[ed]].end());
}
int query(LL v){
    int L = -1, R = -1;
    for (int i = 1; i <= num; i++){
        LL _v = v-lazy[i];
        int pos = lower_bound(Bval[i].begin(), Bval[i].end(), Node(_v,0)) - Bval[i].begin();
        if (pos >= 0 && pos < Bval[i].size() && Bval[i][pos].v == _v){
            L = Bval[i][pos].id; break;
        }
    }
    if (L == -1){ return -1; }
    for (int i = num; i > 0; i--){
        LL _v = v - lazy[i];
        int pos = (lower_bound(Bval[i].begin(), Bval[i].end(), Node( _v + 1,0)) - Bval[i].begin())-1;
        if (pos >= 0 && pos < Bval[i].size() && Bval[i][pos].v == _v){
            R = Bval[i][pos].id; break;
        }
    }
    return R - L;
}
int main(){
    //#ifdef kirito
    //    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
    //#endif
    //    int start = clock();
    while (~scanf("%d%d", &n,&q)){
        for (int i = 1; i <= n; i++){
            scanf("%lld", &val[i]);
        }
        build();
        for (int i = 1; i <= q; i++){
            int type, l, r, v;
            scanf("%d", &type);
            if (type == 1){
                scanf("%d%d%lld", &l, &r, &v);
                modify(l, r, v);
            }
            else{
                scanf("%lld", &v);
                printf("%d\n", query(v));
            }
        }
    }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
    return 0;
}

 

posted @ 2016-10-06 13:20  キリト  阅读(292)  评论(0编辑  收藏  举报