POJ3067 树状数组+逆序数

设两线段为(x1,y1) ,(x2,y2),
若使两线段相交,需使x1<x2&&y1>y2||x1>x2&&y1<y2.

那么本题就变得很简单了,对东边点x从小到大排序,当x相等时对西边点y从小到大排序,每插入一条线段,就求一下逆序对数。总和即为答案。

代码如下:


 1 #include <stdio.h>
2 #include <string.h>
3 #include <algorithm>
4 #define MAXH 1005
5 using namespace std;
6
7 int n, m, k;
8 struct mem{
9 int x,y;
10 }a[MAXH*MAXH];
11
12 int c[1005];
13 bool cmp(mem a,mem b)
14 {
15 if(a.x==b.x) return a.y<b.y;
16 return a.x<b.x;
17 }
18
19 int lowbit(int x)
20 {
21 return x&(-x);
22 }
23
24 void add(int x)
25 {
26 while(x<=m)
27 {
28 c[x]++;
29 x+=lowbit(x);
30 }
31 }
32
33 int sum(int x)
34 {
35 int mm=0;
36 while(x>0)
37 {
38 mm+=c[x];
39 x-=lowbit(x);
40 }
41 return mm;
42 }
43
44 main()
45 {
46 int i, j, kk=1;
47 __int64 ans;
48 int t;
49 scanf("%d",&t);
50 while(t--)
51 {
52 memset(c,0,sizeof(c));
53 scanf("%d %d %d",&n,&m,&k);
54 for(i=0;i<k;i++)
55 scanf("%d %d",&a[i].x,&a[i].y);
56 sort(a,a+k,cmp);
57 ans=0;
58 for(i=0;i<k;i++)
59 {
60 ans+=sum(m)-sum(a[i].y);
61 add(a[i].y);
62 }
63 printf("Test case %d: %I64d\n",kk++,ans);
64 }
65 }

时间: 2024-08-24 19:09:26

POJ3067 树状数组+逆序数的相关文章

hdu2838Cow Sorting(树状数组+逆序数)

题目链接:点击打开链接 题意描述:给定一个长度为100000的数组,每个元素范围在1~100000,且互不相同,交换其中的任意两个数需要花费的代价为两个数之和.问如何交换使数组有序,花费的代价最小? 解题思路: 1.显然我们知道,要使一个数组有序至少交换的次数(即必须要交换的次数)为数组中的逆序数 2.由于数组的长度比较大所以我们可以通过树状数组来统计结果 此处需要两个树状数组 第一个:记录小于等于某个值的元素的个数 第二个:记录小于等于某个值的元素的和 代码: #include <cstdio

HDU 4911 (树状数组+逆序数)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4911 题目大意:最多可以交换K次,就最小逆序对数 解题思路: 逆序数定理,当逆序对数大于0时,若ak<ak+1,那么交换后逆序对数+1,反之-1. 设原始序列最小逆序对数=cnt 那么,交换K次的最小逆序对数max(0,cnt-k) 在求原始序列最小逆序对数上,朴素暴力复杂度O(n^2)不可取 有以下两种O(nlogn)的方法: ①排序内计算: 主要是利用归并排序内的特性,即相邻两个归并序列逆序情

树状数组+逆序数与顺序数——HDU 2492

对应HDU题目:点击打开链接 Ping pong Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description N(3N20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skil

HDU5196--DZY Loves Inversions 树状数组 逆序数

题意查询给定[L, R]区间内 逆序对数 ==k的子区间的个数. 我们只需要求出 子区间小于等于k的个数和小于等于k-1的个数,然后相减就得出答案了. 对于i(1≤i≤n),我们计算ri表示[i,ri]的逆序对数小于等于K,且ri的值最大.(ri对应代码中的cnt数组) 显然ri单调不降,我们可以通过用两个指针扫一遍,利用树状数组计算出r数组. 对于每个询问L,R,我们要计算的是∑i=LR[min(R,ri)−i+1] 由于ri具有单调性,那我们直接在上面二分即可,然后记一个前缀和(s数组).

hdu 5193 分块 树状数组 逆序对

题意: 给出n个数,a1,a2,a3,...,an,给出m个修改,每个修改往数组的某个位置后面插入一个数,或者把某个位置上的数移除.求每次修改后逆序对的个数. 限制: 1 <= n,m <= 20000; 1 <= ai <= n 思路: 插入和删除用分块来处理,块与块之间用双向链表来维护,每一块用树状数组来求小于某个数的数有多少个. 外层可以使用分块维护下标,这样添加和删除元素的时候,也很方便,直接暴力.查找权值个数时,使用树状数组比较方便.内层通过树状数组维护权值. 每次更新即

POJ-3067 Japan---树状数组逆序对变形

题目链接: https://vjudge.net/problem/POJ-3067 题目大意: 日本岛东海岸与西海岸分别有N和M个城市,现在修高速公路连接东西海岸的城市,求交点个数. 解题思路: 记每条告诉公路为(x,y), 即东岸的第x个城市与西岸的第y个城市修一条路.当两条路有交点时,满足(x1-x2)*(y1-y2) < 0.所以,将每条路按x从小到达排序,若x相同,按y从小到大排序. 然后按排序后的公路用树状数组在线更新,求y的逆序数之和 即为交点个数. 比如样例 1 42 33 23

Codeforces Round #609 (Div. 2)E--K Integers(贪心+二分+树状数组+逆序对)

K Integers 参考博客:https://blog.csdn.net/Q755100802/article/details/103664555 [题意] 给定一个1到n的排列,可以交换相邻的两个元素. 现在定义一个函数f(x),表示在原排列中,通过交换操作,形成一个1,2,3....x的排列的子串,需要的最小操作步骤. 子串意味着这个排列必须是相邻的.现在你需要求出f(1),f(2),f(3)......f(n). [分析] 在1~x这几个元素相邻的情况下,因为最后排列不存在逆序对,根据贪

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度

【树状数组逆序对】USACO.2011JAN-Above the median

[题意] 给出一串数字,问中位数大于等于X的连续子串有几个.(这里如果有偶数个数,定义为偏大的那一个而非中间取平均) [思路] 下面的数据规模也小于原题,所以要改成__int64才行.没找到测试数据,自己编的几组.简单来说读入每个数,大于等于中位数设为1,小于设为-1,前i个数的和建立一个树状数组,求逆序对. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorit