HDU 5862(离散化+树状数组)

Problem Counting Intersections

题目大意

  给定n条水平或竖直的线段,统计所有线段的交点个数。 (n<=100000)

解题分析

  首先将线段离散化。

  然后将所有线段按照横坐标的顺序,按照先插入再查找再删除的顺序进行操作。

  对于横线 如果是左端点,则将其纵坐标加1,右端点则减1,对于竖线直接求和就行了。

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17
 18 #define N 100008
 19 #define M 50008
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define rep(x,y,z) for (int x=y;x<=z;x++)
 25 #define repd(x,y,z) for (int x=y;x>=z;x--)
 26 const int mo  = 1000000007;
 27 const int inf = 0x3f3f3f3f;
 28 const int INF = 2000000000;
 29 /**************************************************************************/
 30 struct line{
 31     int x,y,z;
 32     line(int x=0,int y=0,int z=0):x(x),y(y),z(z){}
 33     bool operator <(const line b) const{
 34         return x<b.x || x==b.x && z<b.z;
 35     }
 36 }a[N],b[N],c[N*2];
 37
 38 int val[N*4],cnt;
 39
 40 int id(int x){
 41     return lower_bound(val+1,val+cnt+1,x)-val;
 42 }
 43
 44 struct Binary_Indexed_Tree{
 45     int a[N*5];
 46     void clear(){
 47         clr(a,0);
 48     }
 49     void insert(int x,int val){
 50         for (int i=x;i<=N<<2;i+=i & (-i))
 51             a[i]+=val;
 52     }
 53     int sigma(int x){
 54         int res=0;
 55         for (int i=x;i>0;i-=i & (-i))
 56             res+=a[i];
 57         return res;
 58     }
 59     int query(int x,int y){
 60         return sigma(y)-sigma(x-1);
 61     }
 62 }T;
 63
 64 int main(){
 65     int testcase;
 66     scanf("%d",&testcase);
 67     while (testcase--){
 68         int n,na=0,nb=0,nc=0;
 69         cnt=0;
 70         scanf("%d",&n);
 71         rep(i,1,n){
 72             int x1,y1,x2,y2;
 73             scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
 74             val[++cnt]=x1;
 75             val[++cnt]=y1;
 76             val[++cnt]=x2;
 77             val[++cnt]=y2;
 78             if (x1==x2){
 79                 if (y1>y2) swap(y1,y2);
 80                 b[++nb]=line(x1,y1,y2);
 81             }
 82             if (y1==y2){
 83                 if (x1>x2) swap(x1,x2);
 84                 a[++na]=line(y1,x1,x2);
 85             }
 86         }
 87         sort(val+1,val+cnt+1);
 88         cnt=unique(val+1,val+cnt+1)-val-1;
 89         rep(i,1,na){
 90             a[i].x=id(a[i].x);
 91             a[i].y=id(a[i].y);
 92             a[i].z=id(a[i].z);
 93             c[++nc]=line(a[i].y,i,1);
 94             c[++nc]=line(a[i].z,i,3);
 95         }
 96         rep(i,1,nb){
 97             b[i].x=id(b[i].x);
 98             b[i].y=id(b[i].y);
 99             b[i].z=id(b[i].z);
100             c[++nc]=line(b[i].x,i,2);
101         }
102         sort(c+1,c+nc+1);
103         T.clear();
104         LL ans=0;
105         rep(i,1,nc){
106             if (c[i].z==1){
107                 T.insert(a[c[i].y].x,1);
108             }
109             if (c[i].z==2){
110                 ans+=T.query(b[c[i].y].y,b[c[i].y].z);
111             }
112             if (c[i].z==3){
113                 T.insert(a[c[i].y].x,-1);
114             }
115         }
116         printf("%lld\n",ans );
117     }
118 }

  

时间: 2024-08-23 23:49:08

HDU 5862(离散化+树状数组)的相关文章

HDU 4325 离散化+树状数组 或者 不使用树状数组

题意:给出一些花的开放时间段,然后询问某个时间点有几朵花正在开放. 由于ti<1e9,我们需要先将时间离散化,然后将时间点抽象为一个数组中的点,显然,我们需要进行区间更新和单点查询,可以考虑线段树与树状数组两种做法,一般的,树状数组是用来维护区间和与单点修改的,那么,如何通过树状数组进行区间更新和单点查询呢,联想到差分数组,差分数组可以在o(1)的时间内进行区间的更新,但是单点查询的效率为o(n),显然不能用于处理此题,这时,考虑树状数组维护差分数组,就可以o(logn)地进行区间更新(更新差分

hdu 3015 Disharmony Trees (离散化+树状数组)

Disharmony Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 663    Accepted Submission(s): 307 Problem Description One day Sophia finds a very big square. There are n trees in the square. T

hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 481    Accepted Submission(s): 245 Problem Description You were driving along a highway when you got caught by the road p

2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ&#39;s Salesman 【离散化+树状数组维护区间最大值】

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 919    Accepted Submission(s): 290 Problem Description YJJ is a salesman who h

poj 2299 Ultra-QuickSort 离散化 + 树状数组

题目链接:http://poj.org/problem?id=2299 离散化 + 树状数组 教科书例题般的题目 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <vector> #include <stack> #include <set> #include

CodeForces 540E - Infinite Inversions(离散化+树状数组)

花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树状数组,但是发现那些没有交换的数也会产生逆序对数,但我没有算. 经明神提示, 把没有用到的数字段化成点.然后用树状数组算一下就好了. 然后我用一个数组记录每个点的长度.比如 <1,2><5,6>,1,2,3,4,5,6只有1,2,5,6用到了,那么离散化为1,2,3,4,5,f[1]=

HDU Cow Sorting (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838 Cow Sorting Problem Description Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cow

【bzoj4756】[Usaco2017 Jan]Promotion Counting 离散化+树状数组

原文地址:http://www.cnblogs.com/GXZlegend/p/6832263.html 题目描述 The cows have once again tried to form a startup company, failing to remember from past experience that cows make terrible managers!The cows, conveniently numbered 1-N1-N (1≤N≤100,000), organi

POJ 2299 Ultra-QuickSort (离散化+树状数组)

题目链接:POJ 2299 Ultra-QuickSort 求一串序列相邻连个元素交换多少后,是一串上升的序列. 思路:求该串序列的逆序数,数据比较大,要离散化. AC代码: #include<stdio.h> #include<string.h> #include<set> #include<map> #include<algorithm> #define ll __int64 using namespace std; const ll max

hdu 5193 分块 树状数组 逆序对

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