洛谷p1637 三元上升子序列(树状数组
题目描述
Erwin最近对一种叫"thair"的东西巨感兴趣。。。
在含有n个整数的序列a1,a2......an中,
三个数被称作"thair"当且仅当i<j<k且ai<aj<ak
求一个序列中"thair"的个数。
输入输出格式
输入格式:
开始一个正整数n,
以后n个数a1~an。
输出格式:
"thair"的个数
输入输出样例
4 50 18
3
4
6
8
14
15
16
17
21
25
26
Input
4
2 1 3 4
Output
2
Input
5
1 2 2 3 4
Output
7
对样例2的说明:
7个"thair"分别是
1 2 3
1 2 4
1 2 3
1 2 4
1 3 4
2 3 4
2 3 4
说明
约定 30%的数据n<=100
60%的数据n<=2000
100%的数据n<=30000
大数据随机生成
0<=a[i]<=maxlongint
那么如果我们考虑在输入时考虑当前的c,那么我们只需找两个小于c并且不同的数
如果位置小于c且值小于c的数没有重复,那么我们可以得到是,以c结尾的三元组数量是
n*(n-1)/2,
有重复元素怎么办呢,因为这样计数,1,2,2,3,4,计算以4结尾的三元组时,会算到2,2,4
那么怎么解决这个问题..
解决1:
换种计数方法,考虑中间元素b,我们只需考虑b之前有多少个严格小于它的元素数量u,之后有多少严格大于它的元素v
于是中间元素b的三元组对答案的贡献就是u*v
于是我们可以算两遍,第一遍算u第二遍算v
附上代码...
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 using namespace std;
6 const int maxn=1e5+7;
7 int N,w;
8 typedef long long ll;
9 ll t[maxn],u[maxn],v[maxn];
10 struct node{
11 int id,v;node(){};node(int id,int v):id(id),v(v){};
12 };
13 node a[maxn];
14 int lowbit(int x){
15 return x&-x;
16 }
17 void add(int n,int x){
18 while(n<=N){
19 t[n]+=x;
20 n+=lowbit(n);
21 }
22 }
23 int sum(int n){
24 int ans=0;
25 while(n){
26 ans+=t[n];
27 n-=lowbit(n);
28 }
29 return ans;
30 }
31 bool cmp1(node a,node b){
32 return a.v<b.v;
33 }
34 bool cmp2(node a,node b){
35 return a.id<b.id;
36 }
37 int main(){
38 int n,x;scanf("%d",&n);
39 for(int i=1;i<=n;++i){
40 scanf("%d",&x);
41 a[i]=node(i,x);
42 }
43 sort(a+1,a+1+n,cmp1);
44 int cnt=1,st=1,pre=a[1].v;
45 for(int i=2;i<=n;++i){
46 while(i<=n&&a[i].v==pre) i++;
47 for(int j=st;j<i;++j){
48 a[j].v=cnt;
49 }
50 st=i;pre=a[i].v;
51 cnt++;
52 }
53 for(int j=st;j<=n;++j) a[j].v=cnt;
54 //for(int i=1;i<=n;++i) printf("%d,",a[i].v);printf("\n");
55 N=cnt;
56 sort(a+1,a+1+n,cmp2);
57 ll ans=0;
58 for(int i=1;i<=n;++i){
59 u[i]=sum(a[i].v-1);
60 add(a[i].v,1);
61 }
62 memset(t,0,sizeof(t));
63 for(int i=n;i>=1;--i){
64 v[i]=sum(N)-sum(a[i].v);
65 ans+=u[i]*v[i];
66 add(a[i].v,1);
67 }
68 printf("%lld\n",ans);
69 return 0;
70 }
其实也可以这么写,
因为sum(N)=n-i的,因为是倒着插入的,所以当你插入n时,正好已经插入了n-n个元素,
插入n-1时,正好已经插入了一个元素,所以n-i-sum(a[i].v)的意思是,当前插入的所有元素减去小于等于v的元素个数,
那么剩下的一定都大于v,sum(N)=大于v的元素个数+小于等于v的元素个数
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 using namespace std;
6 const int maxn=1e5+7;
7 int N,w;
8 typedef long long ll;
9 ll t[maxn],u[maxn],v[maxn];
10 struct node{
11 int id,v;node(){};node(int id,int v):id(id),v(v){};
12 };
13 node a[maxn];
14 int lowbit(int x){
15 return x&-x;
16 }
17 void add(int n,int x){
18 while(n<=N){
19 t[n]+=x;
20 n+=lowbit(n);
21 }
22 }
23 int sum(int n){
24 int ans=0;
25 while(n){
26 ans+=t[n];
27 n-=lowbit(n);
28 }
29 return ans;
30 }
31 bool cmp1(node a,node b){
32 return a.v<b.v;
33 }
34 bool cmp2(node a,node b){
35 return a.id<b.id;
36 }
37 int main(){
38 int n,x;scanf("%d",&n);
39 for(int i=1;i<=n;++i){
40 scanf("%d",&x);
41 a[i]=node(i,x);
42 }
43 sort(a+1,a+1+n,cmp1);
44 int cnt=1,st=1,pre=a[1].v;
45 for(int i=2;i<=n;++i){
46 while(i<=n&&a[i].v==pre) i++;
47 for(int j=st;j<i;++j){
48 a[j].v=cnt;
49 }
50 st=i;pre=a[i].v;
51 cnt++;
52 }
53 for(int j=st;j<=n;++j) a[j].v=cnt;
54 //for(int i=1;i<=n;++i) printf("%d,",a[i].v);printf("\n");
55 N=cnt;
56 sort(a+1,a+1+n,cmp2);
57 ll ans=0;
58 for(int i=1;i<=n;++i){
59 u[i]=sum(a[i].v-1);
60 add(a[i].v,1);
61 }
62 memset(t,0,sizeof(t));
63 for(int i=n;i>=1;--i){
64 v[i]=n-i-sum(a[i].v);
65 ans+=u[i]*v[i];
66 add(a[i].v,1);
67 }
68 printf("%lld\n",ans);
69 return 0;
70 }
洛谷p1637 三元上升子序列(树状数组的更多相关文章
- 洛谷P1637 三元上升子序列
P1637 三元上升子序列 48通过 225提交 题目提供者该用户不存在 标签云端 难度提高+/省选- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 为什么超时啊 a的数据比较 ...
- [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?
其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...
- 洛谷P3688/uoj#291. [ZJOI2017]树状数组
传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...
- 洛谷P3368 【模板】树状数组 2
P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...
- 洛谷P3374 【模板】树状数组 1
P3374 [模板]树状数组 1 140通过 232提交 题目提供者HansBug 标签 难度普及/提高- 提交 讨论 题解 最新讨论 题目描述有误 题目描述 如题,已知一个数列,你需要进行下面两 ...
- 洛谷 P3368 【模板】树状数组 2
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- 洛谷 P3374 【模板】树状数组 1
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- 树状数组模板(pascal) 洛谷P3374 【模板】树状数组1
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- 洛谷 P3368 【模板】树状数组 2(区间修改点查询)
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
随机推荐
- 前端知识(二)01-NPM包管理器-谷粒学院
目录 一.简介 二.使用npm管理项目 1.项目初始化 2.修改npm镜像 3.npm install命令的使用 4.其它命令 一.简介 什么是NPM NPM全称Node Package Manage ...
- CSS3+JS完美实现放大镜模式
最近看到一篇讲放大镜的文章,实践后感觉效果非常好,这里分享给大家. 效果如下: 其实现核心: CSS函数,如:calc() -- 动态计算:var() -- 使用自定义变量 CSS伪元素:::befo ...
- ES数据库高可用配置
ES高可用集群部署 1.ES高可用架构图 2.创建ES用户组 1.Elasticsearch不能在 root 用户下启动,我们需要在三台机器上分创建一个普通用户# 创建elastic用户 userad ...
- 1、剑指offer-数组——二维数组中的查找
*题目描述* **在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含 ...
- (009)每日SQL学习:Oracle各个键说明(转)
原文地址:http://www.agiledata.org/essays/keys.html 本文概述关系数据库中为表指定主键的策略.主要关注于何时使用自然键或者代理键的问题.有些人会告诉你应该总是使 ...
- 8.3 Customizing Git - Git Hooks 钩子 自动拉取 自动部署 提交工作流钩子,电子邮件工作流钩子和其他钩子
https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks https://github.com/git/git/blob/master/temp ...
- 网页小实验——用canvas生成精灵动画图片
实验目标:借助canvas把一张国际象棋棋子图片转换为一组适用于WebGL渲染的精灵动画图片,不借助其他图片处理工具,不引用其他库只使用原生js实现. 初始图片如下: 一.图片分割 将初始图片分割为六 ...
- LOJ10159旅游规划
题目描述 W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流.但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员. 具体来说,W 市的交通网络十分简 ...
- 利用Javascript制作网页特效(图像特效)
图像是文本的解释和说明,在网页中的适当位置放置一些图像,不仅可以使文本更加容易阅读,而且可以使网页更加具有吸引力. 当鼠标指针经过图像时图像振动效果 ①:在head标签内输入以下代码: <sty ...
- $().arr使用
$("#handmoney").attr("readonly","readonly"); 只读 $("img").att ...