【Luogu P1637】 三元上升子序列
对于每个数$a_i$,易得它对答案的贡献为 它左边比它小的数的个数$\times$它右边比它大的数的个数。
可以离散化后再处理也可以使用动态开点的线段树。
我使用了动态开点的线段树,只有需要用到这个节点的时候才新建这个节点,这里我是在进行修改的时候新建的。
时间复杂度$O(n\log \rm MAX\_INT)$,空间复杂度$O(n\log \rm MAX\_INT)$(常数真的很大)
以下是代码,不清楚的地方已标出。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll MAXN = 3e4 + , inf = 0x7fffffffLL + 5LL; ll ans = , kans[MAXN], a[MAXN], n; struct node{ ll data;
node *lc, *rc; void pushup() {
data = ;
if(lc) data += lc->data;
if(rc) data += rc->data;
} node() {
data = ;
lc = rc = NULL;
} } *st1 = new node, *st2 = new node; //建立两棵线段树 ll query(node *&cur, ll l, ll r, ll ql, ll qr) {
if(!cur) return ; //防止访问无效内存
if(ql <= l && r <= qr) {
return cur->data;
}
ll mid = (l + r) >> , ans = ;
if(ql <= mid) ans += query(cur->lc, l, mid, ql, qr);
if(qr > mid) ans += query(cur->rc, mid + , r, ql, qr);
return ans;
} void modify(node *&cur, ll l, ll r, ll q, ll k) {
if(!cur) cur = new node; //新建节点
if(l == r) cur->data += k;
else {
ll mid = (l + r) >> ;
if(q <= mid) modify(cur->lc, l, mid, q, k);
else modify(cur->rc, mid + , r, q, k);
cur->pushup();
}
} void solve() {
for(ll i = ; i < n; i++) {
kans[i] = query(st1, , inf, , a[i] - ); //得到它左边比它小的数的个数
modify(st1, , inf, a[i], );
}
for(ll i = n - ; i >= ; i--) {
kans[i] *= query(st2, , inf, a[i] + , inf); //得到右边比它大的数的个数
modify(st2, , inf, a[i], );
}
} int main () {
cin >> n;
for(ll i = ; i < n; i++) cin >> a[i], a[i]+=; //为了防止访问到0,这里直接加上2,是不改变结果的
solve();
for(ll i = ; i < n; i++) ans += kans[i];
cout << ans << endl;
return ;
}
【Luogu P1637】 三元上升子序列的更多相关文章
- 【luogu P1637 三元上升子序列】 题解
题目链接:https://www.luogu.org/problemnew/show/P1637 BIT + 离散化. 读题得数据规模需离散化.BIT开不到longint这么大的数组. 对于题目所求的 ...
- Luogu P1637 三元上升子序列【权值线段树】By cellur925
题目传送门 emmm..不开结构体的线段树真香! 首先我们知道"三元上升子序列"的个数就是对于序列中的每个数,**它左边比他小的数*它右边比他大的数**.但是如何快速求出这两个数? ...
- 洛谷P1637 三元上升子序列
P1637 三元上升子序列 48通过 225提交 题目提供者该用户不存在 标签云端 难度提高+/省选- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 为什么超时啊 a的数据比较 ...
- P1637 三元上升子序列
thair 好,这个naive的东西因为只有三元,很好求解.只要把每个数之前小的L[i]与之后大的R[i]求一下即可. 求两次逆序对即可.那么答案便是∑(L[i]*R[i]); 对于更高元的,胡雨菲写 ...
- 洛谷p1637 三元上升子序列(树状数组
题目描述 Erwin最近对一种叫"thair"的东西巨感兴趣... 在含有n个整数的序列a1,a2......an中, 三个数被称作"thair"当且仅当i&l ...
- 【洛谷P1637】三元上升子序列
题目大意:给定一个长度为 N 的序列,求有多少个三元组满足 \(i<j<k,a_i<a_j<a_k\). 题解:这是一类二维偏序问题,与逆序对问题类似. 对于序列中每个点来说, ...
- [LeetCode] Increasing Triplet Subsequence 递增的三元子序列
Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the ar ...
- Luogu 3402 最长公共子序列(二分,最长递增子序列)
Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...
- (luogu P1410)子序列 [TPLY]
子序列 题目链接:https://www.luogu.org/problemnew/show/P1410 吐槽: 这道题做得我心累 本来想好好练一练dp 刷刷水题来练练手感 于是乎打开了(普及+/提高 ...
随机推荐
- 改善WPF应用程序性能的10大方法 (转发)
WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密,给用户的感觉是它太吃资源了,WPF程序的性能和硬件确实有很大的关系 ...
- 微信小程序开发入门首选
推荐一本书吧,直接上图,微信开发,微信网页开发,微信小程序开发,都用得着. 推荐一本书吧,直接上图,微信开发,微信网页开发,微信小程序开发,都用得着. 推荐一本书吧,直接上图,微信开发,微信网页开发, ...
- 【C++】【MFC】创建新的线程函数
DWORD WINAPI MyThreadProc (LPVOID lpParam){ somestruct* pN = (somestruct*)lpParam; // 将参数转为你的类型 ... ...
- UVA 12118 Inspector's Dilemma(连通性,欧拉路径,构造)
只和连通分量以及度数有关.不同连通分量只要连一条边就够了,连通分量为0的时候要特判.一个连通分量只需看度数为奇的点的数量,两个端点(度数为奇)是必要的. 如果多了,奇点数也一定是2的倍数(一条边增加两 ...
- Memory Usage Performance Guidelines
https://developer.apple.com/library/content/documentation/Performance/Conceptual/ManagingMemory/Arti ...
- 前端知识体系之CSS及其预处理器SASS/LESS
如果你是个前端设计师,很多时候我们都在写CSS,CSS是定义页面样式的脚本,并不是一种编程语言,只是一行行单纯的描述页面元素的样子,如果对英语熟练的话,它像说话一样简单,这里举个简单的例子: body ...
- 3218: 字符串字符统计—C语言
3218: 字符串字符统计—C语言 时间限制: 1 Sec 内存限制: 128 MB提交: 270 解决: 129[提交][状态][讨论版][命题人:smallgyy] 题目描述 编写一函数,由实 ...
- Java时间为什么从1970-01-01 00:00:00 000开始
不仅仅是Java,几乎所有的语言的时间都是从这一刻开始算起的. 原因:java起源于UNIX系统,而UNIX认为1970年1月1日0点是时间纪元. 最初计算机操作系统是32位,而时间也是用32位表示. ...
- javaweb基础(26)_jsp标签库开发二
一.JspFragment类介绍 javax.servlet.jsp.tagext.JspFragment类是在JSP2.0中定义的,它的实例对象代表JSP页面中的一段符合JSP语法规范的JSP片段, ...
- 【DBA-Oracle】更改Oracle数据字符集_转为常用的ZHS16GBK
A.oracle server 端 字符集查询 select userenv('language') from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LAN ...