屏保
来源:互联网 发布:淘宝店铺出售法律风险 编辑:程序博客网 时间:2024/04/27 21:09
题意:
一个有热带鱼的水族馆,水族馆的底端是由沙石形成的供鱼玩耍的地方,沙石的高度可以设置,水位也可以设置。水族馆可以看做是一个二维平面,宽看作N-1 列,最左端的横坐标为0,最右端横坐标为N-1,每个整数横坐标都对应着一个沙石的高度H_i(0<=i<=N-1),相邻横坐标i 和i+1 之间的沙石可以看做是由(i,H_i)和(i+1,H_i+1)这两个点形成的线段。如果水位为h,水覆盖着水族馆底端到y=h 这个区域,如果有部分沙石在水面以上,这部分形成一个岛屿。对于不同的沙石情况,你想知道被水覆盖区域的面积,即水位以下总面积减去水中沙石的面积。
N(3<=N<=100,000)
询问数M(1<=M<=100,000)
沙石高度H_i(0<=Hi<=1000)
分析:
设ans[h] 为 水面高度为h时水面下沙石的面积。
考虑两个相邻点组成的图形的面积对ans[h]的贡献,设它们的高度分别是X和Y。
1°
2° min(x,y)<
3°max(x,y)
所以我们可以在ans[h]记录答案关于h的二次项系数、一次项系数、常数。用线段树上述三种情况进行区间修改。
#include <cstdio>#include <algorithm>using namespace std;typedef double Do;const int N = 1e5 + 10;int h[N];double pass[N / 100 * 4][3],ans[N][3];int n,m;void push(int tot,int l,int r) { if (!pass[tot][0] && !pass[tot][1] && !pass[tot][2]) return; if (l == r) { for (int i = 0;i < 3;i ++) ans[l][i] += pass[tot][i]; } else { for (int i = 0;i < 3;i ++) { pass[tot << 1][i] += pass[tot][i]; pass[tot << 1 | 1][i] += pass[tot][i]; } } for (int i = 0;i < 3;i ++) pass[tot][i] = 0;}void ins(int tot,int l,int r,int l1,int r1,Do a,Do b,Do c) { if (l1 > r1) return; if (l1 <= l && r1 >= r) { pass[tot][2] += a; pass[tot][1] += b; pass[tot][0] += c; push(tot,l,r); return; } push(tot,l,r); int mid = (l + r) >> 1; if (l1 <= mid) ins(tot << 1,l,mid,l1,r1,a,b,c); if (mid < r1) ins(tot << 1 | 1,mid + 1,r,l1,r1,a,b,c);}void add(int X,int Y,int t) { double x = X,y = Y; if (x > y) swap(x,y); ins(1,1,1000,1,min(X,Y),0,t,0); double z = y - x; ins(1,1,1000,min(X,Y) + 1,max(X,Y),-t * 1 / (2 * z),t * y / z,t * (x + z / 2 - y * y / (2 * z))); ins(1,1,1000,max(X,Y) + 1,1000,0,0,t * (x + y) / 2);}void get(int tot,int l,int r,int pos) { push(tot,l,r); if (l == r) return; int mid = (l + r) >> 1; if (pos <= mid) get(tot << 1,l,mid,pos); else get(tot << 1 | 1,mid + 1,r,pos);}int main() { scanf("%d%d",&n,&m); for (int i = 1;i <= n;i ++) scanf("%d",&h[i]); for (int i = 1;i < n;i ++) add(h[i],h[i + 1],1); for (int i = 1;i <= m;i ++) { char type; scanf(" %c",&type); if (type == 'Q') { int H; scanf("%d",&H); Do Ans = (n - 1) * H; H = min(H,1000); get(1,1,1000,H); Do cur = 0,x = 1; for (int j = 0;j <= 2;j ++) { cur += x * ans[H][j]; x *= H; } printf("%.3lf\n",Ans - cur); } else { int k,H; scanf("%d%d",&k,&H); k ++; if (k < n) add(h[k],h[k + 1],-1),add(H,h[k + 1],1); if (k > 1) add(h[k - 1],h[k],-1),add(h[k - 1],H,1); h[k] = H; } }}
0 0
- 屏保
- 屏保
- 屏保
- 泡泡屏保
- 屏保程序
- 制作屏保
- 去除屏保
- 屏保 KeyguardLock
- 气泡屏保
- 简单屏保
- android 屏保
- bcb 屏保
- 做屏保
- 禁止屏保与开启屏保
- 如何编写屏保
- 修改屏保口令
- 黑客字幕屏保
- 屏保密码全攻略
- GDOI模拟 20150806
- 数据离散化
- 最大二分匹配hdu5093
- HDoj 4496 D-City(并查集)
- 1.设计模式概述
- 屏保
- Doing Homework again SDUT 2076
- 单例模式
- Ganymed SSH2 模拟类似FileZilla远程传输文件(基于SCP协议)
- hdu 1241 Oil Deposits(经典dfs)
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- Jenkins hash算法
- poj 2391 最大流+floyd+二分(转移避难)
- java设计模式(1) - 单例模式