• HYSBZ 2957 分块


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2957

    题意:中文题面

    思路: 来自此博客

    首先明确问题,对于每栋楼房的斜率K=H/X,问题就是问有多少个楼房的K比前面所有楼房的K都要大。

    这题树套树当然可以,但是挺麻烦的,本渣觉得最简单就是分块……

    将N个楼房分成T块,不断维护每个块内楼房的可视序列,如一个块内楼房的高度分别为(3 1 4 2 6 7)那么这个块内楼房的可视序列就是(3 4 6 7)(注意不同的块内是不干扰的,如第一个块可视序列为(3 4 6),第二块的序列可以是(5 7 8))

    对于每个修改,我们只需对每个块内的楼房暴力维护可视序列就行了,O(N/T)

    对于每个询问,我们只需一个块一个块看,不断维护到目前为止的可视序列中K的最大值kmax(不在可视序列内的楼房的K值一定不大),那么对于查询每个块的时候,可以二分可视序列找到第一个大于kmax的位置,若没有则这个块的所有楼房都不可见,如果存在,那么这个位置后的此块中的可视序列楼房都能看见,那么就更新答案和kmax,不断往后做

    #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 = 100000 + 10;
    int belong[MAXN], block, num, L[MAXN], R[MAXN];
    int n, m;
    double h[MAXN];
    vector<double>Bh[MAXN];
    void build(){
        block = int(sqrt(n + 0.5));
        num = n / block; if (n%block){ num++; }
        for (int i = 1; i <= num; i++){
            Bh[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;
        }
    }
    void modify(int pos, int val){
        Bh[belong[pos]].clear(); h[pos] = double(val) / pos;
        for (int i = L[belong[pos]]; i <= R[belong[pos]]; i++){
            if (i == L[belong[pos]]){
                Bh[belong[pos]].push_back(h[i]); continue;
            }
            if (h[i]>Bh[belong[pos]][Bh[belong[pos]].size() - 1]){
                Bh[belong[pos]].push_back(h[i]);
            }
        }
    }
    int query(){
        int ans = 0;
        double maxh = 0;
        for (int i = 1; i <= num; i++){
            int pos = upper_bound(Bh[i].begin(), Bh[i].end(), maxh) - Bh[i].begin();
            if (pos != Bh[i].size()){
                ans += Bh[i].size() - pos;
                maxh = Bh[i][Bh[i].size() - 1];
            }
        }
        return ans;
    }
    int main(){
    //#ifdef kirito
    //    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
    //#endif
    //    int start = clock();
        while (~scanf("%d%d", &n, &m)){
            memset(h,0,sizeof(h));
            build();
            for (int i = 1; i <= m; i++){
                int pos, hei;
                scanf("%d%d", &pos, &hei); 
                modify(pos, hei);
                printf("%d
    ", query());
            }
        }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
        return 0;
    }
  • 相关阅读:
    .net core 反编译一小段
    .net core 自动注入。。。。懵逼。。
    css 过渡效果
    sqlserver 插入语句
    sqlserver 删除表 外键
    关于selenium的CI、框架……
    浅析selenium的PageFactory模式
    java使用IO读写文件总结
    selenium结合sikuliX操作Flash网页
    记阿里巴巴的一次面试
  • 原文地址:https://www.cnblogs.com/kirito520/p/5945427.html
Copyright © 2020-2023  润新知