HDU 5592
2015-12-16 14:20
295 查看
原题:
http://acm.hdu.edu.cn/showproblem.php?pid=5592
线段树的变形,先说思路。
题目中给出了当前节点之前的逆序对数,则p[i]-p[i-1]就是对于p[i]来说,新增的逆序数,也就是比p[i]大的数,所以这时要考虑倒着处理,用线段树维护哪些数已经使用,哪些还未使用,p[i]-p[i-1]+1就是在还能用的序列中,第几大的数。我们用1表示数还没用,用0表示已经用了,这里就用到线段树的变形,每个节点维护着当前区间有几个1,我们的原则是先访问线段树的右节点,再左节点,因为右边的数大嘛。
需要注意的是,刚开始要将所有的叶子节点更新为1,再就是,当右节点不满足条件,要进入左节点时,一定用val减去右节点的值。
http://acm.hdu.edu.cn/showproblem.php?pid=5592
线段树的变形,先说思路。
题目中给出了当前节点之前的逆序对数,则p[i]-p[i-1]就是对于p[i]来说,新增的逆序数,也就是比p[i]大的数,所以这时要考虑倒着处理,用线段树维护哪些数已经使用,哪些还未使用,p[i]-p[i-1]+1就是在还能用的序列中,第几大的数。我们用1表示数还没用,用0表示已经用了,这里就用到线段树的变形,每个节点维护着当前区间有几个1,我们的原则是先访问线段树的右节点,再左节点,因为右边的数大嘛。
需要注意的是,刚开始要将所有的叶子节点更新为1,再就是,当右节点不满足条件,要进入左节点时,一定用val减去右节点的值。
#include<stdio.h> #include<string.h> #define maxn 50005 int a[maxn],b[maxn],tree[maxn<<2]; int n,k; void init(){ k = 1; while(k<n) k <<= 1; memset(tree,0,sizeof(tree)); } void upgrade(int index,int val){ index = index + k - 1; tree[index] += val; index /= 2; while(index){ tree[index] = tree[index*2] + tree[index*2+1]; index /= 2; } } int query(int index,int l,int r,int val){ if(l==r) return l; int m = (l+r)/2; if(tree[index*2+1]>val) query(index*2+1,m+1,r,val); else query(index*2,l,m,val-tree[index*2+1]); } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d",&n); init(); for(int i = 1;i<=n;i++){ scanf("%d",&a[i]); upgrade(i,1); } for(int i = n;i>0;i--){ int val = a[i] - a[i-1]; b[i] = query(1,1,k,val); upgrade(b[i],-1); } for(int i = 1;i<n;i++) printf("%d ",b[i]); printf("%d\n",b ); } return 0; }
相关文章推荐
- 用反射改进工厂模式
- c# 根据中文汉字获取到拼音
- map 常用方法
- eclipse 安装本地adt插件
- vs2008下MFC中采用ado连接MySQL(ODBC、非ODBC或C API方式)
- Linux磁盘与块设备名的对应问题
- js 为label标签和div标签赋值
- 由 Session 和 Cookie 的区别说起
- Maven_POM配置详解
- Java中的String类
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
- iOS实现麦克风捕获和AAC编码
- Windows程序设计--击键消息和字符消息
- Spark SQL 之 Migration Guide
- English Learning
- 199. Binary Tree Right Side View (Tree, Stack)
- jmeter之如何减负-实现稳定超高并发测试(性能调优)
- 百度地图(截图)
- GDB十分钟教程
- 关于CoreData的多线程安全问题