UESTC_冰雪奇缘 CDOJ 843

艾莎女王又开始用冰雪魔法盖宫殿了。

她决定先造一堵墙,于是释放魔法让形为直角梯形的冰砖从天而降,定入冻土之中。

现在你将回答女王的询问:某段冻土上冰砖的面积。

注:多块冰砖之间会互相重叠,重叠部分要多次计算。

Input

第一行一个整数n,表示有n个冰砖先后定入了冻土之中。

冻土上刚开始并没有冰砖。

接下来n行,每行6个整数,x1i,h1i,x2i,h2i,li,ri。

表示一次如图所示的冰砖下落,并询问在这之后,落在[li,ri]内冰砖的总面积。

2≤n≤100000,−108≤li<ri≤108,−108≤x1i<x2i≤108,0≤h1i,h2i≤10000,x2i−x1i≤105

Output

输出n行,每行输出一个浮点数,作为对该询问的回答。误差小于1e-6的回答都被当作正确回答

解题报告

首先由于范围很大,我们对X轴上的点进行离散化

注意到这个四边形就是给一段区间增加一段等差数列.

并且注意到等差数列叠加后依然还是等差数列

那么我们在线段树中就存储四个值:

1.double st; //该区间左端应该加的值

2.double ed; //该区间右端应该加的值

3.double k;  //等差数列的k值,不多说

4.double sum; //该区间的面积之和

那么面积我们就转换成梯形计算:

SUM = (st + ed) * 0.5 * Len; //注意到这个Len是这个区间的实际长度!!

这样.

还有两点需要注意!

1.区间建立的时候是[L,R] → [L,mid] + [mid,R]

2. updata操作有三种情况,三种情况的更新各不同,这点需要注意

分别对应ql ,qr 在mid 的左 / 右 / 中三种情况,需分开讨论

注意上以上几点,那么本题也就迎刃而解了.

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn = 1e5 + 500;
  7 int n;
  8 int pos[maxn*9];
  9 int hashpos[maxn*9];
 10
 11 typedef struct Query
 12 {
 13 int l,r,x1,y1,x2,y2,id[6];
 14 };
 15
 16 typedef struct Data
 17 {
 18 int l,r,len;
 19 double sum,st,ed,k;
 20 void updata(const double &x,const double &y,const double &z)
 21  {
 22      st += x;
 23      ed += y;
 24      k += z;
 25      sum += (double)(x+y)*len*0.5;
 26  }
 27 };
 28
 29
 30 Query q[maxn*2];
 31 Data tree[maxn*6];
 32 int size = 0;
 33
 34
 35 void push_up(int cur)
 36 {
 37    tree[cur].sum = tree[cur*2].sum + tree[cur*2+1].sum;
 38 }
 39
 40 inline double get_(int x1,int x2,double st,double k)
 41 {
 42    return (double)(hashpos[x2]-hashpos[x1]) * k + st;
 43 }
 44
 45
 46 void push_down(int cur)
 47 {
 48   double st = tree[cur].st;
 49   double ed = tree[cur].ed;
 50   double k = tree[cur].k;
 51   int l = tree[cur].l;
 52   int r = tree[cur].r;
 53   int mid = l + (r-l)/2;
 54   double news = get_(tree[cur].l,mid,st,k);
 55   tree[2*cur].updata(st,news,k);
 56   tree[2*cur+1].updata(news,ed,k);
 57   tree[cur].st = tree[cur].ed = tree[cur].k = 0.;
 58 }
 59
 60 void build_tree(int cur,int l,int r)
 61 {
 62    tree[cur].l = l , tree[cur].r = r;
 63    tree[cur].len = hashpos[r] - hashpos[l];
 64    tree[cur].st = tree[cur].ed = tree[cur].k = tree[cur].sum = 0.;
 65    if (r -l > 1)
 66     {
 67         int mid = l + (r-l)/2;
 68         build_tree(2*cur,l,mid);
 69         build_tree(2*cur+1,mid,r);
 70     }
 71 }
 72
 73 void updata(int ql,int qr,int cur,double st,double ed,double k)
 74 {
 75    int l = tree[cur].l , r = tree[cur].r;
 76    if (l >= ql && r <= qr)
 77     {
 78         tree[cur].updata(st,ed,k);
 79     }
 80    else
 81     {
 82         push_down(cur);
 83         int mid = l + (r-l) / 2;
 84         //三种情况,分开讨论
 85         if (qr <= mid) updata(ql,qr,2*cur,st,ed,k);
 86         else if(ql >= mid) updata(ql,qr,2*cur+1,st,ed,k);
 87         else
 88          {
 89              double news = get_(ql,mid,st,k);
 90              updata(ql,mid,2*cur,st,news,k);
 91              updata(mid,qr,2*cur+1,news,ed,k);
 92          }
 93         push_up(cur);
 94     }
 95 }
 96
 97 double query(int ql,int qr,int cur)
 98 {
 99    int l = tree[cur].l , r = tree[cur].r;
100    if (l >= ql && r <= qr)
101     return tree[cur].sum;
102    else
103     {
104         push_down(cur);
105         double res = 0.;
106         int mid = l + (r-l)/2;
107         if (mid > ql)
108          res += query(ql,qr,2*cur);
109         if (mid < qr)
110          res += query(ql,qr,2*cur+1);
111         push_up(cur);
112         return res;
113     }
114 }
115
116 inline double getk(int x1,int x2,int y1,int y2)
117 {
118    return (double)(y2-y1) / (double)(x2-x1);
119 }
120
121
122
123 int main(int argc,char *argv[])
124 {
125   scanf("%d",&n);
126   for(int i = 0 ; i < n ; ++ i)
127    {
128          int x1,y1,x2,y2,l,r;
129          scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&l,&r);
130          q[i].id[0] = size;
131          pos[size++] = x1;
132          q[i].id[1] = size;
133          pos[size++] = x2;
134          q[i].id[2] = size;
135          pos[size++] = l;
136          q[i].id[3] = size;
137          pos[size++] = r;
138          q[i].x1 = x1;
139          q[i].x2 = x2;
140          q[i].y1 = y1;
141          q[i].y2 = y2;
142          q[i].l = l;
143          q[i].r = r;
144    }
145   memcpy(hashpos,pos,sizeof(int)*size);
146   sort(hashpos,hashpos+size);
147   int c = unique(hashpos,hashpos+size) - hashpos;
148   for(int i = 0 ; i < size ; ++ i)
149    pos[i] = lower_bound(hashpos,hashpos+c,pos[i]) - hashpos;
150   build_tree(1,0,c-1);
151   for(int i = 0 ; i < n ; ++ i)
152    {
153          int x1 = q[i].x1;
154          int y1 = q[i].y1;
155          int x2 = q[i].x2;
156          int y2 = q[i].y2;
157          double k = getk(x1,x2,y1,y2);
158          updata(pos[q[i].id[0]],pos[q[i].id[1]],1,(double)y1,(double)y2,k);
159          double res = query(pos[q[i].id[2]],pos[q[i].id[3]],1);
160          printf("%.9lf\n",res);
161    }
162   return 0;
163 }
时间: 2024-10-16 05:03:32

UESTC_冰雪奇缘 CDOJ 843的相关文章

UESTC_握手 CDOJ 913

握手 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 一群人参加了一次聚会,其中有一些人是好朋友.一对朋友见面后握手且仅握一次手,并且每个人不会和自己握手(废话!).现在告诉你每个人一共握了几次手,请你判断是否存在一种朋友关系满足每个人的握手数. Input 输入多组数据,第一行一个数T,表述数据组数.每组数据第一行输入一个数n,表示有n个人参加了聚

UESTC_棋盘游戏 CDOJ 578

最近昀昀学习到了一种新的棋盘游戏,这是一个在一个N×N的格子棋盘上去搞M个棋子的游戏,游戏的规则有下列几条: 棋盘上有且仅有一个出口 开始时没有哪个棋子在出口,而且所有棋子都不相邻(这里的相邻是指上下左右四个方向) M个棋子分别记为1到M 每个时刻你可以移动一个棋子向它相邻的四个格子移动一步 你需要保证任意时刻棋盘上所有棋子都不相邻 只有当前棋盘上编号最小的棋子移动到出口时才能取走改棋子. 所有棋子都移走的时候游戏结束 对于一个给定的游戏局面,昀昀最少要多少步才能结束这个游戏呢? Input 第

UESTC_方老师的分身 II CDOJ 915

方老师的分身 II Time Limit: 10000/5000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方老师计算出了走路时间最长的那个分身所用的时间.于是有个特殊的分身(据说是方老师真身!)就不想如此古板的走最短路了!由于这个分身的特殊性,这个分身对于单向边可以当双向边走.但是这个特殊的分身想走最短路的同时,要求至少经过k条边. Input 有多组数据 第一行两个整数n,m(1≤n

UESTC_贪吃蛇 CDOJ 709

相信大家都玩过贪吃蛇游戏吧. 在n×m的迷宫中,有着一条长度不超过9的贪吃蛇,它已经将所有的食物吃光了,现在的目标是移动到出口. 它走的时候不能碰到自己的身体,也不能碰到墙壁.(如果贪吃蛇的长度>3并且下一步要走到自己的尾部,是合法的) 问它能不能走到出口,如果能,最少要移动几步? Input 数据包含多组数据,请读入到文件末尾EOF 每组数据第一行包含两个整数n,m(1≤n,m≤15)代表迷宫的大小. 接下来n行,每行包含一个长度为m的字符串,来表示迷宫. 字符串中仅包含..#.@.1 ~ 9

UESTC_敢说就敢做 CDOJ 631

敢说就敢做 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status beap总是自诩敢说又敢做,又到了情人节,为了体现自己的勇气可嘉,beap决定给自己喜欢的女生买玫瑰花,以此表达自己的爱意.到花店里,他发现一共有K种花,同时他从网上得知,送N朵花的花语是LOVE,所以他决定在所有的花里面选N朵出来送给心爱的女生,但是又为了显示自己买了那么多种花,他决定这K

UESTC_我要长高 CDOJ 594

韩父有N个儿子,分别是韩一,韩二…韩N.由于韩家演技功底深厚,加上他们间的密切配合,演出获得了巨大成功,票房甚至高达2000万.舟子是名很有威望的公知,可是他表面上两袖清风实则内心阴暗,看到韩家红红火火,嫉妒心遂起,便发微薄调侃韩二们站成一列时身高参差不齐.由于舟子的影响力,随口一句便会造成韩家的巨大损失,具体亏损是这样计算的,韩一,韩二…韩N站成一排,损失即为C×(韩i与韩i+1的高度差(1≤i<N))之和,搞不好连女儿都赔了.韩父苦苦思索,决定给韩子们内增高(注意韩子们变矮是不科学的只能增高

UESTC_魔法少女小蟹 CDOJ 710

小蟹是一名魔法少女,能熟练的施放很多魔法. 有一天魔法学院上课的时候出现了这样一道题,给一个6位数,让大家用自己的魔法,把这个6位数变成另一个给定的6位数. 小蟹翻了下魔法书,发现她有以下6种魔法: 将当前魔杖指向的数字与最左端的一个数字调换位置. 将当前魔杖指向的数字与最右端的一个数字调换位置. 将当前魔杖指向的数字+1.(若当前魔杖指向的数字为9则无效) 将当前魔杖指向的数字−1.(若当前魔杖指向的数字为0则无效) 将当前魔杖向右移动一位. 将当前魔杖向左移动一位. 最开始,她的魔杖指向的是

UESTC_方老师分身 I CDOJ 914

方老师分身 I Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方老师为了开更多讲座,于是他分身了!早上他都在某一个教室分身,然后各个分身分别赶去各个不同的n个教室(当然每个教室都要有且只有一个分身).晚上各个分身都赶回之前分身时的教室,合并成一个人(不需要同时回去).但是教室间的路十分崎岖,而且是单向的.当然即便只是方老师的分身,那也是相当厉害的,

UESTC_冬马党 CDOJ 882

冬马党 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 终于到了冬马党与雪菜党决战的时候了,为了方便,他们的决战之地可看成一个n×m矩阵. 决战前夜,冬马党安插在雪菜党中的内线告诉白学家Kuros,雪菜党已经在他们的决战之地埋下了地雷. 白学家Kuros根据多年来扫雷的经验,推测出雪菜党一定不会在相邻的格子里都放地雷.(两个格子相邻指它们共享一条边)