BZOJ2141&洛谷1975 排队 【线段树套treap】
题目
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。
红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足i<j且hi>hj的(i,j)数量。
幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。
输入格式
第一行为一个正整数n,表示小朋友的数量;
第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;
第三行为一个正整数m,表示交换操作的次数;
以下m行每行包含两个正整数ai和bi,表示交换位置ai与位置bi的小朋友。
输出格式
输出文件共m+1行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。
输入样例
3
130 150 140
2
2 3
1 3
输出样例
1
0
3
提示
【样例说明】
未进行任何操作时,(2,3)满足条件;
操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
对于15%的数据,n,m \le 15n,m≤15;
对于30%的数据,n,m \le 200n,m≤200;
在剩下的70%数据中:
存在15%的数据,h_ih
i
各不相同;
存在15%的数据,1^{10} \le h_i \le 1^{60}1
10
≤h
i
≤1
60
;
以上两类数据不存在交集。
对于100%的数据,1 \le m \le 2\times 10^31≤m≤2×10
3
,1 \le n \le 2 \times 10^41≤n≤2×10
4
,1 \le h_i \le 10^91≤h
i
≤10
9
,a_i \ne b_ia
i
≠b
i
,1 \le a_i,b_i \le n1≤a
i
,b
i
≤n。
题解
数据结构什么的查错真的是查得想死啊,,
不过A了就很舒服~~
蒟蒻没写过treap,今天一跃写了线段树套treap,感觉整个人要虚脱
嘴上AC还是不难:
先用离散化 + 树状数组算出初始的逆序对
之后没交换L和R,我们只需要考虑他们对答案带来的影响:
①L和R,若h[L]>h[R],交换后逆序对会减少1;若h[L] < h[R],交换后逆序对会增加1
②L和R与他们两边的元素的相对位置不变,只对(L,R)区间内产生影响,只要求出(L,R)区间内比h[L]和h[R]小和大的个数来更新答案即可
【一开始忘记判l>r WA了,后来发现一开始求逆序对时没考虑相等,又WA 。。QAQ】
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
#define lbt(u) (u & -u)
using namespace std;
const int maxn = 20005,maxm = 5000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
int n,m,A[maxn],rt[4 * maxn];
int Siz,ls[maxm],rs[maxm],val[maxm],cnt[maxm],siz[maxm],rnd[maxm];
void pup(int u){
siz[u] = siz[ls[u]] + siz[rs[u]] + cnt[u];
}
void lturn(int& u){
int t = rs[u]; rs[u] = ls[t]; ls[t] = u;
pup(u); pup(t); u = t;
}
void rturn(int& u){
int t = ls[u]; ls[u] = rs[t]; rs[t] = u;
pup(u); pup(t); u = t;
}
void ins(int& u,int v){
if (!u) {
u = ++Siz; val[u] = v;
rnd[u] = rand(); siz[u] = cnt[u] = 1;
}
else if (val[u] > v) {
siz[u]++; ins(ls[u],v);
if (rnd[ls[u]] > rnd[u]) rturn(u);
}
else if (val[u] < v) {
siz[u]++; ins(rs[u],v);
if (rnd[rs[u]] > rnd[u]) lturn(u);
}
else cnt[u]++,siz[u]++;
}
void del(int &u,int v)
{
if(!u) return;
if(val[u] == v)
{
if(cnt[u] > 1) cnt[u]--,siz[u]--;
else if(ls[u] * rs[u] == 0) u = ls[u] + rs[u];
else if(rnd[ls[u]] > rnd[rs[u]]) rturn(u),del(u,v);
else lturn(u),del(u,v);
}
else if(v < val[u]) siz[u]--,del(ls[u],v);
else siz[u]--,del(rs[u],v);
}
int getpre(int r,int v){
int ans = 0,u = rt[r];
while (true){
if (!u) return ans;
else if (val[u] > v) u = ls[u];
else if (val[u] < v) ans += siz[ls[u]] + cnt[u],u = rs[u];
else return ans + siz[ls[u]];
}
}
int getpost(int r,int v){
int ans = 0,u = rt[r];
while (true){
if (!u) return ans;
else if (val[u] < v) u = rs[u];
else if (val[u] > v) ans += siz[rs[u]] + cnt[u],u = ls[u];
else return ans + siz[rs[u]];
}
}
void build(int u,int l,int r){
for (int i = l; i <= r; i++) ins(rt[u],A[i]);
if (l == r) return;
int mid = l + r >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
}
void modify(int u,int l,int r,int pos,int v){
del(rt[u],A[pos]); ins(rt[u],v);
if (l == r) return;
int mid = l + r >> 1;
if (mid >= pos) modify(u << 1,l,mid,pos,v);
else modify(u << 1 | 1,mid + 1,r,pos,v);
}
int Getpre(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R) return getpre(u,v);
int mid = l + r >> 1;
if (mid >= R) return Getpre(u << 1,l,mid,L,R,v);
else if (mid < L) return Getpre(u << 1 | 1,mid + 1,r,L,R,v);
else return Getpre(u << 1,l,mid,L,R,v) + Getpre(u << 1 | 1,mid + 1,r,L,R,v);
}
int Getpost(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R) return getpost(u,v);
int mid = l + r >> 1;
if (mid >= R) return Getpost(u << 1,l,mid,L,R,v);
else if (mid < L) return Getpost(u << 1 | 1,mid + 1,r,L,R,v);
else return Getpost(u << 1,l,mid,L,R,v) + Getpost(u << 1 | 1,mid + 1,r,L,R,v);
}
int b[maxn],s[maxn],Ans;
void add(int u){while (u <= n) s[u] ++,u += lbt(u);}
int query(int u){int tot = 0; while (u) tot += s[u],u -= lbt(u); return tot;}
int getn(int x){return lower_bound(b + 1,b + 1 + n,x) - b;}
int main(){
n = read(); int l,r;
REP(i,n) b[i] = A[i] = read();
sort(b + 1,b + 1 + n);
for (int i = n; i; i--){
int t = getn(A[i]);
Ans += query(t - 1);
add(t);
}
printf("%d\n",Ans);
build(1,1,n);
m = read();
while (m--){
l = read(); r = read();
if (l > r) swap(l,r);
if (l == r) {printf("%d\n",Ans); continue;}
if (A[l] < A[r]) Ans++;
if (A[l] > A[r]) Ans--;
if (l < r - 1){
Ans -= Getpre(1,1,n,l + 1,r - 1,A[l]);
Ans += Getpost(1,1,n,l + 1,r - 1,A[l]);
Ans -= Getpost(1,1,n,l + 1,r - 1,A[r]);
Ans += Getpre(1,1,n,l + 1,r - 1,A[r]);
}
modify(1,1,n,l,A[r]); modify(1,1,n,r,A[l]);
swap(A[l],A[r]);
printf("%d\n",Ans);
}
return 0;
}
BZOJ2141&洛谷1975 排队 【线段树套treap】的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 初学树套树:线段树套Treap
前言 树套树是一个十分神奇的算法,种类也有很多:像什么树状数组套主席树.树状数组套值域线段树.\(zkw\)线段树套\(vector\)等等. 不过,像我这么弱,当然只会最经典的 线段树套\(Trea ...
- BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】
BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...
- BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)
题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...
- bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...
- 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...
- bzoj3196 二逼平衡树 树套树(线段树套Treap)
Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 4697 Solved: 1798[Submit][Status][D ...
- 洛谷P4396 [AHOI2013]作业(树套树)
题意 题目链接 Sol 为什么一堆分块呀..三维数点不应该是套路离线/可持久化+树套树么.. 亲测树状数组套权值线段树可过 复杂度\(O(nlog^2n)\),空间\(O(nlogn)\)(离线) # ...
- 【洛谷】【线段树】P1471 方差
[题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...
随机推荐
- 在O(1)时间复杂度删除链表节点
题目描述: 给定一个单链表中的一个等待被删除的节点(非表头或表尾).请在在O(1)时间复杂度删除该链表节点. 您在真实的面试中是否遇到过这个题? Yes 样例 给定 1->2->3-> ...
- react的redux中间件
redux 的中间件(对dispatch功能的拦截和增强,一般不用自己写,有插件) dispath是一个方法,可以自行中间拦截更改: store.dispatch = function(action) ...
- 手写promise
写在前面: 在目前的前端分开中,我们对于异步方法的使用越来越频繁,那么如果处理异步方法的返回结果,如果优雅的进行异步处理对于一个合格的前端开发者而言就显得尤为重要,其中在面试中被问道最多的就是对Pro ...
- P4746 C’s problem(c)
时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 题目描述 小C是一名数学家,由于它自制力比较差,经常通宵研究数学问题. 这次它因为这个数 ...
- JavaScript ES6功能概述(ECMAScript 6和ES2015 +)
JavaScript在过去几年中发生了很大的变化.这些是您今天可以开始使用的12项新功能! 该语言的新增内容称为ECMAScript 6.它也称为ES6或ES2015 +. 自1995年JavaScr ...
- 关于使用Java开发Mis系统
如何使用Java开发一个小型的信息管理系统,首先我们应该知道要使用什么样的方法. 1.Java基础 2.JSP+Servlet+JavaBean JSP是服务器端的编程语言,见得比较多的是在一些网站上 ...
- python字符编码小结
首先简要说一下各种字符编码: 1. ASCII 计算机只认识0101,但如何让计算机认识人类语言?将每个字母和符号给予固定的编号,然后将这个编号转换成二进制,计算机就可以正确识别这些字母与符号,同时计 ...
- 【转】iPhone通讯录AddressBook.framework和AddressBookUI.framework的应用
通讯录中联系人相关的应用iPhone提供了两个框架:AddressBook.framework和AddressBookUI.framework,使用这两个框架我们可以在程序中访问并显示iPhone数据 ...
- Flow Problem HDU - 3549
Flow Problem HDU - 3549 Network flow is a well-known difficult problem for ACMers. Given a graph, yo ...
- python-01 spider原理
用Python可以做什么?可以做日常任务,比如自动备份你的MP3:可以做网站,很多著名的网站包括YouTube就是Python写的:可以做网络游戏的后台,很多在线游戏的后台都是Python开发的.总之 ...