HDU4132 How Far Can Drive At Most 离散化+树状数组/线段树
来源:互联网 发布:巨人网络公司地址 编辑:程序博客网 时间:2024/05/02 01:03
Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=4132
【前言】
没想到这么简单的一道题可以被做的这么复杂= =
拿到题想到可以用离散化,于是很快就想出来了。
(其实想到离散化的时候还想到了线段树,但是后面居然把这么重要的东西忘了。)
开始时偷懒,用hash和set写了交上去,返回TLE。
觉得可能是stl太慢了,于是去掉hash和set,写了个二分,又TLE了。
自己的二分一直都不敢保证,于是换了个bsearch,还是TLE。
突然发现,原来修改段的时候应该不能线性扫描!
于是添加了个树状数组进去,便华丽丽的AC了。
然后把自己的二分也改好了。
【思路】
将所有可能的点离散化,最多有100000个点。
扫描所有段,对于要增加时间的段都要修改。包括一开始对所有段都加1。
要注意的是,比如段[a,b],则修改[a,b-1]。
这样做的好处是扫描时只需对当前结点判断即可。
然后从小到大扫描所有结点,查出当前段的值。
如果这段路可以走完,则继续走。否则结束。同时计算路程。
想必这道题数据比较水,没用__int64还AC了。
其实一开始用树状数组的时候还提醒自己要用__int64的,结果……
【代码】
//树状数组版本【修改区间,查询节点】(具体参考这里)
#include <iostream>#include <string>#include <cmath>#include <vector>#include <set>#include <map>#include <algorithm>using namespace std;const int maxn = 50000;struct node{int s;int e;int v;}seg[maxn+5];struct hashnode{int rv;int id;}index[maxn*2+5];bool cmp(const hashnode &a, const hashnode &b){return a.rv<b.rv;}int f[maxn*2+5];inline int lowbit(int x){return x & (-x);}inline void _update(int x, int d){int i;for (i=x; i>0; i-=lowbit(i)){f[i] += d;}}inline void update(int l, int r, int d){_update(l-1, -d);_update(r, d);}inline int getpt(int x, int n){int i, s = 0;for (i=x; i<=n; i+=lowbit(i)){s += f[i];}return s;}int bs(int v, int s, int t){int l=s-1, r=t+1, m, ans;while(l<=r){m = (l+r)>>1;if (v<=index[m].rv){ans = m;r = m-1;}else l = m+1;}return index[ans].id;}int main(){int t;int len;double amt;int n;int i, j;int a, b;int end;double ans;scanf("%d", &t);while(t--){scanf("%d %lf", &len, &amt);scanf("%d", &n);index[1].rv = 0;index[2].rv = len;for (i=0,j=3; i<n; i++,j+=2){scanf("%d %d %d", &seg[i].s, &seg[i].e, &seg[i].v);index[j].rv = seg[i].s;index[j+1].rv = seg[i].e;}end = j-1;sort(index+1, index+end+1, cmp);index[1].id = 1;for (i=2,j=2; i<=end; i++){if (index[i].rv!=index[j-1].rv){index[j].rv = index[i].rv;index[j].id = j;j++;}}end = j-1;memset(f, 0, sizeof(f));update(1, end-1, 1);for (i=0; i<n; i++){a = bs(seg[i].s, 1, end);b = bs(seg[i].e, 1, end);update(a, b-1, seg[i].v);}ans = 0;for (i=1; i<end && fabs(amt)>1e-6; i++){a = index[i+1].rv-index[i].rv;b = getpt(i, end);if (a*1.0>amt/b){ans += amt/b;amt = 0;}else{ans += a;amt -= a*b;}}printf("%.2lf\n", ans);}return 0;}
//线段树版本
#include <iostream>#include <string>#include <cmath>#include <vector>#include <set>#include <map>#include <algorithm>using namespace std;const int maxn = 50000;struct node{int s;int e;int v;}seg[maxn+5];struct hashnode{int rv;int id;}index[maxn*2+5];bool cmp(const hashnode &a, const hashnode &b){return a.rv<b.rv;}int bs(int v, int s, int t){int l=s-1, r=t+1, m, ans;while(l<=r){m = (l+r)>>1;if (v<=index[m].rv){ans = m;r = m-1;}else l = m+1;}return index[ans].id;}struct treenode{int left, right;treenode *pl, *pr;int add;}tree[maxn*4+5];int tct;treenode *new_node(){treenode *p = &tree[tct++];p->pl = p->pr = NULL;p->left = p->right = -1;p->add = 0;return p;}treenode *init(int l, int r){treenode *root;root = new_node();root->left = l;root->right = r;root->add = 0;if (l!=r){int m = (l+r)/2;root->pl = init(l, m);root->pr = init(m+1, r);}return root;}void updatetree(treenode *root, int l, int r, int d){int m = (root->left+root->right)>>1;if (l==root->left && r==root->right){root->add += d;return; }if (r<=m){updatetree(root->pl, l, r, d);}else if (l>m){updatetree(root->pr, l, r, d);}else {updatetree(root->pl, l, m, d);updatetree(root->pr, m+1, r, d);}}int get(treenode *root, int v){if (root->left==root->right) return root->add;int m = (root->left+root->right)>>1;if (v<=m) return get(root->pl, v) + root->add;else return get(root->pr, v) + root->add;}int main(){int t;int len;double amt;int n;int i, j;int a, b;int end;double ans;scanf("%d", &t);while(t--){scanf("%d %lf", &len, &amt);scanf("%d", &n);index[1].rv = 0;index[2].rv = len;for (i=0,j=3; i<n; i++,j+=2){scanf("%d %d %d", &seg[i].s, &seg[i].e, &seg[i].v);index[j].rv = seg[i].s;index[j+1].rv = seg[i].e;}end = j-1;sort(index+1, index+end+1, cmp);index[1].id = 1;for (i=2,j=2; i<=end; i++){if (index[i].rv!=index[j-1].rv){index[j].rv = index[i].rv;index[j].id = j;j++;}}end = j-1;tct = 0;treenode *root;root = init(1, end);updatetree(root, 1, end-1, 1);for (i=0; i<n; i++){a = bs(seg[i].s, 1, end);b = bs(seg[i].e, 1, end);updatetree(root, a, b-1, seg[i].v);}ans = 0;for (i=1; i<end && fabs(amt)>1e-6; i++){a = index[i+1].rv-index[i].rv;b = get(root, i);if (a*1.0>amt/b){ans += amt/b;amt = 0;}else{ans += a;amt -= a*b;}}printf("%.2lf\n", ans);}return 0;}
【P.S】
jay说线段树不好搞,我说不会,跟树状数组一样。
他说要分很多种情况,我说肯定是你理解错了。
于是打出了线段树的版本。
虽然平时基本都是偷懒,只打树状数组不打线段树。
但是这里1A了。
- HDU4132 How Far Can Drive At Most 离散化+树状数组/线段树
- HDU4132 noj[1304] BJF: How Far Can Drive At Most 区间叠加 计算和 超级帅的题目
- 离散化 + 线段树(树状数组) + 线扫描法
- codeforces Gym100589H Count Subarrays 树状数组/线段树+离散化
- [BZOJ3333]排队计划(离散化+树状数组+线段树)
- hdu 5862 Counting Intersections 【线段树/树状数组+离散化】
- HDU5877 Weak Pair dfs + 线段树/树状数组 + 离散化
- POJ3109_Inner Vertices_扫描线段|坐标离散化|树状数组
- 树状数组--离散化
- HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)
- POJ 2761 树状数组离线+离散化 附:线段树解法
- POJ3378:Crazy Thairs(动态规划+线段树或树状数组+离散化+高精度)
- nylg 600 花儿朵朵 //离散化+树状数组或线段树
- 组队赛6:线段树离散化+树状数组并哈希
- 【POJ】2299 - Ultra-QuickSort(离散化 & (树状数组 | 线段树))
- HDU 3333 树状数组(线段树) + 离散化 + 离线处理
- POJ 2299 Ultra-QuickSort (树状数组求逆序数 || 线段树 +离散化)
- Codeforces Round #401 (Div. 2) E 离散化 + 树状数组/线段树
- window.open 参数
- Django+apache+python+mod_python的环境搭建
- 读书
- asp.net 点击后退时,提示网页已过期,怎么样解决?
- 淘宝12月12日活动完成攻略
- HDU4132 How Far Can Drive At Most 离散化+树状数组/线段树
- java设计模式之单例模式Singleton
- 【Doing4】ACM之Java新手速成
- java统计指定文件的大小以及包含的文件夹和文件数
- 工作中运用的tomcat 配置、使用介绍
- USACO Section 2.4 The Tamworth Two - 又犯2了..又把一个简单的问题整复杂了..
- SSH服务器安装及配置
- Flex和spring集成时需要的SpringFactory
- 设置zencart当前页面位置导航(zencart面包屑)