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\n", query()); } } //#ifdef LOCAL_TIME // cout << "[Finished in " << clock() - start << " ms]" << endl; //#endif return 0; }