hdu1394 分治 or 线段树
利用分治求一次逆序数,然后每次把第一个元素放到末尾,设该交换元素的值为x,设上一次求得的逆序数为y,那么此时的逆序数等于y - x + (n - x - 1),减去x是因为x作为第一个元素,其后共有x个元素小于x,移动x会导致逆序数减少x个,而加上 (n - x - 1) 是因为将x移动到末尾,其前面(n - 1)个元素中会有(n - x - 1)个元素大于x。
此题的复杂度在于求第一次逆序数O(nlgn),后面每次移动元素求更新后的逆序数时间是O(1),因此总的复杂度为(nlgn)。
AC代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 5000 +5; int a[maxn], c[maxn]; int solve(int l, int r){ int mid = (l + r) / 2; if( l == r) return 0; int ans = 0; ans += solve(l, mid) + solve(mid + 1, r); // Merge int b[maxn]; int x = l, y= mid + 1; int k = 0; while(x <= mid && y <= r){ if(a[x] <= a[y]){ b[k++] = a[x++]; } else { ans += mid + 1 - x; b[k++] = a[y++]; } } while(x <= mid) b[k++] = a[x++]; while(y <= r) b[k++] = a[y++]; k = 0; for(int i = l; i <= r; ++i) a[i] = b[k++]; return ans; } int main(){ int n; while(scanf("%d", &n) == 1){ for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); } memcpy(c, a, sizeof(a)); int ans = solve(0, n-1); int x = ans; for(int i = 0; i < n; ++i){ ans = min(ans, x + n - 1 - 2 * c[i]); x = x + n - 1 - 2 * c[i]; } printf("%d\n",ans); } return 0; }
线段树也能做这个题,每个区间保存的值代表[l, r]中总出现多少元素,每次加入x元素时,查找区间[x + 2, n]即可得到该元素的加入会增加多少逆序数。
贴上线段树代码:
#include<cstdio> #define min(x,y) (x) < (y) ? x : y const int maxn = 4 * 5000 + 5; int a[5000 + 5]; struct node{ int L, R; int cnt; }t[maxn]; void Build(int l, int r, int cur){ t[cur].L = l, t[cur].R = r; t[cur].cnt = 0; if(l == r) return; int mid = (l + r) / 2; Build(l, mid, cur << 1); Build(mid + 1, r, (cur << 1) + 1); } void add(int c, int cur){ int l = t[cur].L, r = t[cur].R; t[cur].cnt++; if(l == r) return; int mid = (l + r) / 2; if(c <= mid) add(c, cur << 1); else add(c, (cur << 1) + 1); } int find1(int l, int r, int cur){ //search the Inversion (logn) int l1 = t[cur].L, r1 = t[cur].R; if(l == l1 && r == r1) return t[cur].cnt; int mid = (l1 + r1) / 2; if(r <= mid) return find1(l, r, cur << 1); else if(l >= mid + 1) return find1(l, r, (cur << 1) + 1); else return find1(l, mid, cur << 1) + find1(mid + 1, r, (cur << 1) + 1); } int main(){ int n; while(scanf("%d", &n) == 1){ Build(1, n, 1); int ans = 0; for(int i = 0; i < n; ++i){ scanf("%d", &a[i]); a[i]++; add(a[i], 1); if(a[i] + 1 <= n) ans += find1(a[i] + 1, n, 1); } int x = ans; for(int i = 0; i < n; ++i){ ans = min(ans, x + n + 1 - 2 * a[i]); x = x + n + 1 - 2 * a[i]; } printf("%d\n",ans); } return 0; }
如有不当之处欢迎指出!
hdu1394 分治 or 线段树的更多相关文章
- 【BZOJ2001】[HNOI2010]城市建设(CDQ分治,线段树分治)
[BZOJ2001][HNOI2010]城市建设(CDQ分治,线段树分治) 题面 BZOJ 洛谷 题解 好神仙啊这题.原来想做一直不会做(然而YCB神仙早就切了),今天来怒写一发. 很明显这个玩意换种 ...
- BZOJ3711 Druzyny 最大值分治、线段树
传送门 被暴力包菜了,然而还不会卡-- 有一个很暴力的DP:设\(f_i\)表示给\(1\)到\(i\)分好组最多可以分多少组,转移枚举最后一个组.接下来考虑优化这个暴力. 考虑:对于每一个位置\(i ...
- BZOJ4860 BJOI2017 树的难题 点分治、线段树合并
传送门 只会线段树……关于单调队列的解法可以去看“重建计划”一题. 看到路径长度$\in [L,R]$考虑点分治.可以知道,在当前分治中心向其他点的路径中,始边(也就是分治中心到对应子树的根的那一条边 ...
- 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)
闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...
- [BJOI2017]树的难题 点分治,线段树合并
[BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...
- 【BZOJ4317】Atm的树 动态树分治+二分+线段树
[BZOJ4317]Atm的树 Description Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径 ...
- luoguU60884 【模板】动态点分治套线段树
题目连接:https://www.luogu.org/problemnew/show/U60884 题意:有N个点,标号为1∼N,用N−1条双向带权通道连接,保证任意两个点能互相到达. Q次询问,问从 ...
- [CF1303G] Sum of Prefix Sums - 点分治,李超线段树
给定一棵 \(n\) 个点的带点权的树,求树上的路径 \(x_1,...,x_k\) ,最大化 \(\sum_{i=1}^k ia_{x_i}\) Solution 树上路径问题可用点分治. 考虑如何 ...
- ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...
随机推荐
- python_如何读写csv数据
案例: 通过股票网站,我们获取了中国股市数据集,它以csv数据格式存储 Data,Open,High,Low,Close,Volume,Adj Close 2016-06-28,8.63,8.47,8 ...
- 2017 .NET 開發者須知
筆記-Scott Hanselman 的 2017 .NET 開發者須知 转载http://blog.darkthread.net/post-2017-01-16-dotnet-dev-should- ...
- 开发步骤Dubbo、spring mvc、springboot、SSM整合开发步骤
一.Dubbo开发步骤: 链接:https://pan.baidu.com/s/1pMPO1kf 密码:9zaa 第一: 1.创建consumer工程2.在pom.xml文件下添加配置3.添加appl ...
- 使用jQuery的ajax调用action的例子
直接使用ajax请求会比较繁琐,但是jQuery为我们提供了简单使用ajax的方法. 下面是一个在jQuery easyUI中,利用ajax请求,使下拉菜单关联文本框的例子.其中ajax请求就是8-1 ...
- Bilibili/DanmakuFlameMaster: Android开源弹幕引擎·烈焰弹幕使 ~ JNI source:Bilibili/NativeBitmapFactory
https://github.com/Bilibili/DanmakuFlameMaster
- 准备:新V8即将到来,Node.js的性能正在改变
V8的Turbofan的性能特点将如何对我们优化的方式产生影响 审阅:来自V8团队的Franziska Hinkelmann和Benedikt Meurer. **更新:Node.js 8.3.0已经 ...
- Linux下使用skipfish扫描网站漏洞步骤
skipfish是谷歌开发的网站安全扫描工具. 下载地址:http://pan.baidu.com/s/1kTC66lL svn更新地址(一般链接不上,网速很慢): http://skipfish.g ...
- Python之Suds库调用WCF时复杂参数序列化
今天主要做自动化测技术支持工作,最近一直在做接口自动化这块,前些天在研究将web页面模拟http进行接口自动化,这周杭州那边想测试WCF服务,所以这两天一直在探索.遇到的第一个问题就是服务参数传参序列 ...
- Linux普通用户使用sudo权限启停apache服务
sudo的工作过程如下: 1,用户执行sudo时,系统会主动寻找/etc/sudoers文件,判断该用户是否有执行sudo的权限 2,确认用户具有可执行sudo的权限后,让用户输入密码确认 3,若密码 ...
- ehcache memcache redis 三大缓存男高音[转]
原文链接:http://blog.csdn.net/jationxiaozi/article/details/8509732 最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特 ...