zoukankan      html  css  js  c++  java
  • 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
    ", query(v));
                }
            }
        }
        //#ifdef LOCAL_TIME
        //    cout << "[Finished in " << clock() - start << " ms]" << endl;
        //#endif
        return 0;
    }
  • 相关阅读:
    grep使用多个查询条件--或
    Qt Quick App的两种启动模式
    ICP编程软件配置(烧写KEIL编译后的bin文件)
    C/C++语言中const的用法
    QT小插件类之QRoundProgressBar
    QT实现单个EXE文件
    QT小技巧学习记录
    无线路由器的五种工作模式
    Qt5.4静态编译方法
    Altium Designer极坐标布局方法
  • 原文地址:https://www.cnblogs.com/kirito520/p/5933725.html
Copyright © 2011-2022 走看看