/*
两年前,老师拿这套题来考试,完全只会n^2的做法.
但我总是感觉有NlgN的解法.于是各种查题解。发现几乎大家都是最坏情况n^2的算法水过的。
一年前想起这道题时。功夫不负有心人,在某一个blog里看到了ld大神NlogN的题解。于是准备等哪天有心情时过掉它。然后就拖到了今天。。。
将近两年后再来看,有ld大神题解的那个blog没了....于是大家都是N^2水过的。。。
写下这个NlogN的题解(即使代码的长度被完虐),希望哪一天google出来的前几个有NlogN(或者更好0.0)的算法。
*/
我们可以把一个等腰直角三角形想象成一条条不断变短的线段.
性质1:如果一条线段被另一条完全包含了,则这条线段的存在就没有意义了,删掉.
从x轴从左往右做(也可以把x轴想象成时间轴).
用平衡数(我用splay,因为插入时有可能要删除一个区间)维护一个当前时间的线段集合,由于性质1,线段的上端和下端都单调递减
维护出两个数据,总长度L,这些线段的并一共有多少处不连续(记为S)
用堆维护一个x轴坐标为关键字的优先队列.
三种操作
1插入一条线段
2删除一条线段(长度已经减到0了)
3.某条线段不再与上一条线段相交了
ans=Σ(l+l-s*(x2-x1)*(x2-x1)/2//所有时间间隔之间的梯形面积之和
(求点赞,求存在感。。。)
效率分析:
每次操作是均摊logN的,只有操作1会最多增加3个操作(删除一个,与前一个线段分离可能有一个,后一个线段与这个线段分离可能有一个)
而一共只有n个操作1
于是效率是NlogN的
代码写得比较捉急...用来对拍还行...要看的话请加油...
#include#include #include #include #include #define itserror (cout<<"error!!!!!!!!!"< earse;2->split;3->insert;4->count; int argument1, argument2; handle() { } ; handle(int t, int a, int a1, int a2) : time(t), attr(a), argument1(a1), argument2(a2) { } ;} buf;priority_queue heap;struct splay_tree{ struct tree_node { tree_node() { tree[0] = 0; tree[1] = 0; tree[2] = 0; } ; bool is_head; //is_head int tot_head;// int tot_point;//tot_point int tree[3]; //0->left_son;1->right_son;2->father int top_plus_time, bottom; int add_for_ans; int awaytime; LL tot_add; inline int top(int time) { return this->top_plus_time - time; } void clear() { is_head = 0; tot_head = 0; this->top_plus_time = 0; add_for_ans = 0; tot_add = 0; } } a[mN]; void getson(int x, int y, int k) { a[x].tree[k] = y; if (y) a[y].tree[2] = x; } int root, tot, lem, rim; splay_tree() { a[0].clear(); root = 1; lem = 2; rim = 3; tot = 3; a[rim].top_plus_time = -1; a[rim].bottom = -1; a[lem].top_plus_time = oo; a[lem].bottom = oo; getson(root, lem, 1); getson(lem, rim, 1); } bool ir(int x) { if (a[a[x].tree[2]].tree[1] == x) return 1; else return 0; } void update(int x) { int l = a[x].tree[0], r = a[x].tree[1]; a[x].tot_add = a[l].tot_add + a[l].add_for_ans + a[r].tot_add + a[r].add_for_ans; a[x].tot_head = a[l].tot_head + a[l].is_head + a[r].tot_head + a[r].is_head; } void rorate(int x) { int fa = a[x].tree[2], k = ir(x); getson(fa, a[x].tree[1 - k], k); getson(a[fa].tree[2], x, ir(fa)); getson(x, fa, 1 - k); update(fa); } void splay(int x, int root) { int fa; if (x == root) return; while (a[x].tree[2] != root) { fa = a[x].tree[2]; if (a[fa].tree[2] != root) { if (ir(x) == ir(fa)) rorate(fa); else rorate(x); } rorate(x); } update(x); } int find_top(int top) { int now = a[root].tree[1], last_now = 0; while (1) { if (a[now].top_plus_time > top) { if (a[now].tree[1] == 0) return now; last_now = now; now = a[now].tree[1]; } else { if (a[now].tree[0] == 0) { splay(now, root); return last_now; } now = a[now].tree[0]; } } itserror ; return 0; } int find_bt(int bot) { int now = a[root].tree[1], last_now; while (1) { if (a[now].bottom < bot) { if (a[now].tree[0] == 0) return now; last_now = now; now = a[now].tree[0]; } else { if (a[now].tree[1] == 0) return last_now; now = a[now].tree[1]; } } itserror ; return 0; } void eraseall(int x) { if (x == 0) return; if (!exist[x]) return; exist[x] = 0; if (a[x].tree[0]) eraseall(a[x].tree[0]); if (a[x].tree[1]) eraseall(a[x].tree[1]); } void refresh(int x, int time) { int fa = a[x].tree[2]; a[x].is_head = 1; a[x].add_for_ans = a[x].top_plus_time - a[x].bottom; if (!ir(x)) { if (a[fa].top(time) > a[x].bottom) { a[fa].awaytime = a[fa].top_plus_time - a[x].bottom; heap.push(handle(a[fa].awaytime, 2, fa, 0)); a[fa].add_for_ans = a[x].bottom - a[fa].bottom; a[fa].is_head = 0; } } else { if (a[fa].bottom < a[x].top(time)) { a[x].awaytime = a[x].top_plus_time - a[fa].bottom; heap.push(handle(a[x].awaytime, 2, x, 0)); a[x].is_head = 0; a[x].add_for_ans = a[fa].bottom - a[x].bottom; } } rorate(x); } bool insert(int top, int bottom, int time) { int tp = find_top(top); splay(tp, root); if (a[tp].bottom <= bottom) return 0; int bt = find_bt(bottom); splay(bt, tp); if (a[bt].top_plus_time >= top) return 0; eraseall(a[bt].tree[0]); ++tot; a[tot].top_plus_time = top; a[tot].bottom = bottom; exist[tot] = 1; buf.time = top - bottom; buf.attr = 1; buf.argument1 = tot; heap.push(buf); getson(bt, tot, 0); refresh(tot, time); refresh(tot, time); splay(tot, root); return 1; } bool erase(int index) { if (exist[index]) { int now = a[index].tree[0]; if (now) { while (a[now].tree[1]) now = a[now].tree[1]; splay(now, root); } getson(a[index].tree[2], a[index].tree[1], ir(index)); splay(a[index].tree[2], root); exist[index] = 0; return 1; } return 0; } bool split(int index, int time) { if (exist[index] && a[index].awaytime == time) { a[index].is_head = 1; a[index].awaytime = -1; a[index].add_for_ans = a[index].top_plus_time - a[index].bottom; splay(index, root); return 1; } return 0; } void result(int time, int& len_, int& sev_) { splay(lem, root); splay(rim, lem); int now = a[rim].tree[0]; if (now) { sev_ = a[now].tot_head + a[now].is_head; len_ = (a[now].tot_add + a[now].add_for_ans) - LL(sev_) * time; } else { len_ = 0; sev_ = 0; } } void log(int x) {// printf("id %d lson %d rson %d fa %d\n",\ x,a[x].tree[0],a[x].tree[1],a[x].tree[2]); if (a[x].tree[0]) log(a[x].tree[0]); if (a[x].tree[1]) log(a[x].tree[1]); }} all; bool operator <(const handle& a, const handle& b){ return (b.time < a.time || (b.time == a.time && b.attr < a.attr));}; LL ans; inline bool hdl(const handle& buf){ switch (buf.attr) { case 1: return all.erase(buf.argument1); break; case 2: return all.split(buf.argument1, buf.time); break; case 3: return all.insert(buf.argument1, buf.argument2, buf.time); break; default: itserror ; } itserror ; return 0;} int main(){ //freopen("/home/cad/input.txt", "r", stdin);// freopen("/home/cad/output.txt", "w", stdout); int n, x, y, d, last_time=-1, last_len, last_sev; scanf("%d\n", &n); for (int i = 0; i < n; i++) { scanf("%d%d%d", &x, &y, &d); if (d == 0) continue; buf.time = x; buf.attr = 3; buf.argument1 = y + d + x; buf.argument2 = y; heap.push(buf); } bool flag = 0; while (!heap.empty()) { handle buf = heap.top(); if (buf.time==5) { int x; x=x+1; } all.log(1);// cout<<"_____________________"< <<"time"< <<"gao"< <<"ans"< < << 1) - LL(buf.time - last_time) * last_sev) * (buf.time - last_time);// printf("*************ans%lld\n",ans); } last_time = buf.time; } hdl(buf); } all.log(1); printf("%.1f\n", ans / 2.0); return 0;}