线段树动态开点之逆序对

对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。
求这段正整数序列中逆序对的数目。
Input
第一行,一个数n,表示序列中有n个数。N<=5*10^5
第二行n个数,表示给定的序列。序列中每个数字不超过10^9
Output
给定序列中逆序对的数目。
Sample Input
6
5 4 2 6 3 1
Sample Output
11

#include<cstdio>
#define ll long long
using namespace std;
const int N=1e7+7;
int n,r;
ll ans;
struct A
{
	int cnt,c[N],lc[N],rc[N];
	int sum(int p,int l,int r,int x,int y)
	{
		if(!p) return 0;
		if(l==x&&r==y)
		    return c[p];
		int mid=l+r>>1;
		if(y<=mid) return sum(lc[p],l,mid,x,y);
		if(x>mid) return sum(rc[p],mid+1,r,x,y);
		return sum(lc[p],l,mid,x,mid)+sum(rc[p],mid+1,r,mid+1,y);
	}

	void add(int &p,int l,int r,int x,int k)
	{
		if(!p)
		    p=++cnt;
		if(l==r)
		{
			c[p]+=k;
			return;
		}
		int mid=l+r>>1;
		if(x<=mid)
		    add(lc[p],l,mid,x,k);
		else
		    add(rc[p],mid+1,r,x,k);
		c[p]=c[lc[p]]+c[rc[p]];
	}
}tree;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x; scanf("%d",&x);
		ans+=tree.sum(r,1,1e9,x+1,1e9);
		tree.add(r,1,1e9,x,1);
	}
	printf("%lld",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/cutemush/p/11833958.html

时间: 2024-08-08 08:11:24

线段树动态开点之逆序对的相关文章

hdu 6183 Color it (线段树 动态开点)

Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B is painting. To prevent him from drawing messy painting, Little D asks you to write a program to maintain following operations. The specific format o

BZOJ_4636_蒟蒻的数列_线段树+动态开点

Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一行一个整数N,然后有N行,每行三个正整数a.b.k. N<=40000 , a.b.k<=10^9 Output 一个数,数列中所有元素的和 Sample Input 4 2 5 1 9 10 4 6

HDU6183 Color it (线段树动态开点)

题意: 一个1e6*1e6的棋盘,有两个操作:给(x,y)加上颜色c,或查找(1,y1)到(x,y2)内的颜色种类数量,最多有50种颜色 思路: 建立50颗线段树,对每个颜色的线段树,维护每个y坐标上x的最小值 但是这样会爆内存,于是动态开点即可 动态开点之后T了一发,就改了下查询的函数,只要有满足在矩形的该颜色,就全线return,果然快了好多 代码: #include<iostream> #include<cstdio> #include<algorithm> #i

线段树动态开点

//zz https://blog.csdn.net/u012972031/article/details/88751811//https://www.luogu.org/problemnew/show/P3372 #include<cstdio> #include<iostream> using namespace std; const int N=300010; struct node{ int ls,rs,lazy; long long sum; }tr[N]; int ro

线段数 --- (单点更新、求逆序对)

Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For

UVALive3938 &quot;Ray, Pass me the dishes!&quot; 线段树动态区间最大和

AC得相当辛苦的一道题,似乎不难,但是需要想仔细, 开始的时候的错误思路----是受之前做过的区间最长连续子串影响http://blog.csdn.net/u011026968/article/details/38357157 区间合并的时候,我直接按照---如果(左子树的最大前缀和长度==左子树的长度 && 右子树的前缀和>0),就合并左前缀,这想法有两个错误:1.右子树的前缀和==0的时候是不是要合并区间呢?题目要求x尽量小,如果x相同y尽量小(x是ans的区间左端点,y是Ans

「模板」线段树静态开点(单点+区间修改)、动态开点

相关讲解资料: 树状数组:https://blog.csdn.net/qq_34374664/article/details/52787481 (线段树预备) 线段树讲解: 初学版:https://blog.csdn.net/zearot/article/details/52280189 进阶完整版:https://www.cnblogs.com/AC-King/p/7789013.html 代码: 完整注释模板一张,参(chao)考(xi)楼上的博客 #include<iostream> #

线段树应开内存

n*2的建树方法,适用于动态建树,就是说没有任何一个节点被浪费的建法.而这里我使用的,或者说大多数人使用的这种用x*2表示左子树 x*2+1表示右子树的建法,是不能只开到n*2的,因为有写节点没用到. 举个列子来说,假如线段树的n = 11,你认为应该建树为22或者23,保守点. 如果你要找[9,9]的区间,就会出现RTE了. 那么开多少才正确呢? 其实,应该是 2^ ( ceiling( log2(n) )+1 ), 即2的log2(n)的上取整加1次幂.

李超线段树 - JSOI2008BlueMary开公司

李超线段树用来在平面内动态插入线段,求\(x=t\)直线与这些线段交点的最值 核心是维护每个区间的"最优势线段",即终点位置处最高的线段,询问室对所有包含\(t\)的区间的最优势线段计算答案,最后取\(max\) 模板题:JSOI2008BlueMary开公司 插入直线,求单点最大值 (看代码) #include<bits/stdc++.h> using namespace std; const int N=50004; #define lc (p<<1) #d