链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394

题意:给一个0-n-1的排列,这个排列中的逆序数为数对 (ai, aj) 满足 i < j and ai > aj的个数。依次把第一个数放到排列的末尾会得到另外n-1个排列,求这n个排列中的最小的逆序数。

思路:关键是要把第一个排列的逆序数求出来,后面的排列可以递推出来。假如第一个逆序数为s0,当把a0从首位移到末位时,新得到的s1应该是在s0的基础上加上比a0大的数的个数,减去比a0小的数的个数。由于这一串数是一个0-n-1的排列,所以比a0大的数的个数为 (n-1)-(a0+1)+1=n-a0-1,比a0小的数的个数为 (a0-1)-0+1=a0,所以s1=n-a0-a0-1.第一次做个题的时候一直想不明白要怎么建树,由于是满足 i < j and ai > aj的条件,所以其实就是对于每个数aj,求比它大的数的个数。建树的时候把每个节点都初始化为0,每当插入一个数,就在这个数对应的叶子节点上加1,同时更新包含这个点的线段所对应的非叶子节点(加1),一层层更新上去,区间求和。这样如果存在某个数,在相应查找的时候就会找到。由于是要找比aj大的数,所以查找范围就是aj-(n-1).如果还是想不明白的话,对着代码手动模拟一遍就清楚了。

这里有个线段树的讲解,虽然不是这道题,但是觉得对理解线段树挺有帮助的。http://hi.baidu.com/semluhiigubbqvq/item/be736a33a8864789f4e4ad18

#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 5005;
int sum[maxn<<2];
int a[maxn];
void PushUP(int rt)//更新每个节点的值,区间求和
{sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{sum[rt]=0;if(l==r) return;int m=(l+r)>>1;build(lson);build(rson);
}
int query(int L,int R,int l,int r,int rt)
{if(L<=l && r<=R)return sum[rt];int m=(l+r)>>1;int s=0;if(L<=m) s+=query(L,R,lson);if(R>m) s+=query(L,R,rson);return s;
}
void update(int p,int l,int r,int rt)
{if(l==r){sum[rt]++;return;}int m=(l+r)>>1;if(p<=m) update(p,lson);else update(p,rson);PushUP(rt);//每次更新了叶子节点后,内部节点也要更新
}
int main()
{int n;while(~scanf("%d",&n)){build(0,n-1,1);int sum=0;for(int i=0;i<n;i++){scanf("%d",&a[i]);sum+=query(a[i],n-1,0,n-1,1);update(a[i],0,n-1,1);}int minm=sum;for(int i=0;i<n;i++){sum+=n-a[i]-a[i]-1;minm=min(minm,sum);}printf("%d\n",minm);}return 0;
}

View Code

转载于:https://www.cnblogs.com/54zyq/p/3268976.html

hdu1394线段树点修改,区间求和相关推荐

  1. 树链剖分+线段树 单点修改 区间求和 模板

    马上要去西安打邀请赛了,存下板子 首先是vector存图的: #include<bits/stdc++.h> using namespace std; #define ll long lo ...

  2. HDU 1166 敌兵布阵(线段树:点更新,区间求和)

    HDU 1166 敌兵布阵(线段树:点更新,区间求和) http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意: 给你n个整数,然后给你多条命令,每条命令如 ...

  3. codeforces round #576 div2 D Welfare State(线段树)[单点修改+区间修改]

    题意:有一些数字,以及一些操作.操作一是单点修改,输入1 b c,将位置b改成c,操作二是输入2 a,将不大于a的数全部改成a.求更改完毕后的数. tag的运用:tag是对被覆盖区间上加一个标记,那么 ...

  4. hdu4417:线段树单点更新区间求和,离线 Super Mario

    Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability ...

  5. (线段树 点更新 区间求和)lightoj1112

    链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#problem/D (密码0817) Description Robin ...

  6. 线段树2 求区间最小值

    线段树2 求区间最小值 递归,DFS,尤其是二叉树,我只要知道我的返回节点就好,因为DFS的顺序一定是一样的,不同的题目和数据范围也是一样的,只是返回节点让DFS的深度不同. 递归的内容只有两部分:1 ...

  7. HDU 1166 敌兵布阵 【线段树-点修改--计算区间和】

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  8. 线段树板子(区间修改)

    测试题目:P3372 [模板]线段树 1 https://www.luogu.org/problemnew/show/P3372 #include<cstdio> #include< ...

  9. 数据结构之线段树进阶(区间更新lazy标记)

    之前说了线段树的点更新和区间求和.其实点更新是区间更新的一种最基础的做法.我们把一个点想像成一个区间的话,不就是最简单的区间更新了嘛. 为什么要把区间更新和点更新分开来看呢?假如我们对区间[l,r]进 ...

最新文章

  1. Spring Security 中最流行的权限管理模型!
  2. Unable to locate Spring NamespaceHandler for XML schema namespace [http://cxf.apache.org/jaxws]
  3. english writing sample for professional
  4. 查询varchar实际大小_微服务和VUE(11): mybatis 动态查询
  5. [vue] 说说你对vue的extend(构造器)的理解,它主要是用来做什么的?
  6. c mysql 工具类_Jave工具——servlet+jsp编程中mysql数据库连接及操作通用工具类
  7. grunt安装与运行
  8. centos7 关闭防火墙的指令_Centos7.3防火墙配置
  9. 从零构建一个图像分类项目 -- 代码
  10. 在BAE tomcat环境下实现讯飞TTS在线文字转语音
  11. 在英文邮件中,如何在开头对收件人进行称呼?
  12. C语言入门 -- Simple Simon 简单的西蒙游戏(2021/1/7)
  13. marked is not a function问题解决
  14. 2022年测试工程师面试题大合集「 功能测试,自动化测试等」300道题
  15. 微信开发调试,常见问题解决
  16. 月薪过2w的IT程序员都是怎么做到的?
  17. DR和DIS的区别?
  18. LVI-SAM imuPreintegration代码解析
  19. ajax感受,有什么缺点,浅谈ajax的优点与缺点
  20. 鸿蒙系统为什么不能退出,鸿蒙系统怎么退回安卓 鸿蒙系统怎么卸载

热门文章

  1. login控件“您的登录尝试不成功。请重试”的解决方法
  2. 动物为什么会预知地震,地震后为什么会下雨?
  3. JavaScript基础——Date对象
  4. VUE2.0开发环境安装
  5. 约瑟夫问题的循环链表实现
  6. 织梦channel标签currentstyle样式无效不起作用
  7. 超简易复制Model对象(为后续备忘录设计模式博文做铺垫)
  8. spring中lazy-init详解
  9. formdata.append加多个值_呆哥数学每日一题 —— 多个最值函数混合向量
  10. hdu 5059 判断数字表示方式以及范围合法(int型之内)