【HDU5862】Counting Intersections

题意

有n条线段,且都平行于坐标轴。对于每条线段,给出两个端点的坐标。问一共有多少个线段的交点。

分析

最最简单的扫描法了。用线段树或者树状数组都可以。

由题目可知,线段只有两种,要么平行于x轴要么平行于y轴。而交点只能是两个不平行的线段产生的。

所有我们以一条平行于x轴的线为扫描线,从下向上扫。先把横坐标进行离散化,然后把平行于y轴的线段拆成上下两个端点。当扫到下端点的时候就在它横坐标+1,当扫到上端点的时候,就在它横坐标-1.对于每一条平行于x轴的线,则将左右端点内的值相加。就酱~

这里一个小细节是,如果是下端点,则先更新,再计算。如果是上端点,则先计算再更新。

讲真,这个题让我很难受,本来以为很快就能解决的题结果TLE了一晚上,刚刚才发现,是数组开小了(;´??Д??`)

线段树

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long LL;
 8 const int maxn=100000+100;
 9 struct Point {
10     int j;//1,0,-1
11     int x,h;
12     int l,r;
13     bool operator <(const Point &rhs)const {
14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
15     }
16 }seg[2*maxn];
17 int T,n,x1,y1,x2,y2,sz,sk;
18 LL ans;
19 int v[2*maxn],sumv[8*maxn];
20 int vv,x;
21 void update(int o,int L,int R){
22     if(L==R){
23         sumv[o]+=vv;
24         return ;
25     }
26     int M=L+(R-L)/2;
27     if(x<=M) update(2*o,L,M);
28     if(x>M) update(2*o+1,M+1,R);
29     sumv[o]=sumv[2*o]+sumv[2*o+1];
30     return ;
31 }
32 int ql,qr;
33 int query(int o,int L,int R){
34     if(ql<=L&&qr>=R){
35         return sumv[o];
36     }
37     int res=0;
38     int M=L+(R-L)/2;
39     if(ql<=M)
40         res+=query(2*o,L,M);
41     if(qr>M)
42         res+=query(2*o+1,M+1,R);
43     return res;
44 }
45 int main(){
46     scanf("%d",&T);
47     for(int t=1;t<=T;t++){
48         sz=sk=ans=0;
49         scanf("%d",&n);
50         for(int i=1;i<=n;i++){
51             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
52             if(x1>x2||y1>y2){
53                 swap(x1,x2);
54                 swap(y1,y2);
55             }
56             if(x1==x2){
57                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
58                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
59                 v[++sk]=x1;
60             }else if(y1==y2){
61                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
62                 v[++sk]=x1,v[++sk]=x2;
63             }
64         }
65         sort(seg+1,seg+1+sz);
66         sort(v+1,v+1+sk);
67         int N=unique(v+1,v+1+sk)-v-1;
68         memset(sumv,0,sizeof(sumv));
69         for(int i=1;i<=sz;i++){
70             if(seg[i].j==0){
71                 ql=lower_bound(v+1,v+1+N,seg[i].l)-v;
72                 qr=lower_bound(v+1,v+1+N,seg[i].r)-v;
73                 ans+=query(1,1,N);
74             }else{
75                 vv=seg[i].j;x=lower_bound(v+1,v+1+N,seg[i].x)-v;
76                 update(1,1,N);
77             }
78         }
79         printf("%lld\n",ans);
80     }
81 return 0;
82 }

树状数组

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <iostream>
 5
 6 using namespace std;
 7
 8 const int maxn=100000+100;
 9 struct Point {
10     int j;//1,0,-1
11     int x,h;
12     int l,r;
13     bool operator <(const Point &rhs)const {
14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
15     }
16 }seg[2*maxn];
17 int T,n,x1,y1,x2,y2,sz,sk,N;
18 long long ans,C[2*maxn];
19 int v[2*maxn];
20 int lowbit(int x){
21     return x&(-x);
22 }
23 void add(int x,int d){
24     while(x<=N){
25         C[x]+=d;
26         x+=lowbit(x);
27     }
28 }
29 long long sum(int x){
30     long long res=0;
31     while(x>0){
32         res+=C[x];
33         x-=lowbit(x);
34     }
35     return res;
36 }
37 int main(){
38     scanf("%d",&T);
39     for(int t=1;t<=T;t++){
40         sz=sk=ans=0;
41         scanf("%d",&n);
42         for(int i=1;i<=n;i++){
43             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
44             if(x1>x2||y1>y2){
45                 swap(x1,x2);
46                 swap(y1,y2);
47             }
48             if(x1==x2){
49                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
50                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
51                 v[++sk]=x1;
52             }else if(y1==y2){
53                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
54                 v[++sk]=x1,v[++sk]=x2;
55             }
56         }
57         sort(seg+1,seg+1+sz);
58         sort(v+1,v+1+sk);
59         N=unique(v+1,v+1+sk)-v-1;
60
61         for(int i=1;i<=sz;i++){
62              if(seg[i].j==0){
63                 int l=lower_bound(v+1,v+1+N,seg[i].l)-v;
64                 int r=lower_bound(v+1,v+1+N,seg[i].r)-v;
65               //  cout<<l<<" "<<r<<endl;
66                 ans+=sum(r)-sum(l-1);
67              }
68              else{
69                 int x=lower_bound(v+1,v+1+N,seg[i].x)-v;
70              //   cout<<x<<" "<<seg[i].j<<endl;
71                 add(x,seg[i].j);
72              }
73         }
74         printf("%lld\n",ans);
75     }
76 return 0;
77 }

原文地址:https://www.cnblogs.com/LQLlulu/p/9040342.html

时间: 2024-10-11 03:34:08

【HDU5862】Counting Intersections的相关文章

【LeetCode】Counting Bits(338)

1. Description Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array. Example: For num = 5 you should return [0,1,1,2,1,2]. 2. Answ

【Leetcode】Counting Bits

题目链接:https://leetcode.com/problems/counting-bits/ 题目: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array. Example: For num = 5 y

【HDU5952】Counting Cliques

题目大意:给定一个\(N\)个点,\(M\)条边的无向图,求图中有多少个大小为\(S\)的团.\(N \le 100,deg(i)\le 20,i\in [1,n]\). 题解: 考虑搜索. 需要确定一种搜索顺序,使得团的计数不重不漏.考虑枚举团中最小编号的节点,且搜索状态转移中只能转移到比当前团中编号最大的节点编号更大的点. 由于\(N\)上限是100,但是每个节点的度数很小,若直接用邻接矩阵进行状态转移,复杂度较高,因此考虑建立邻接表进行转移.在判断两点是否存在边时用邻接矩阵快速判断即可.

【LeetCode】动态规划(上篇共75题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [5] Longest Palindromic Substring 给一个字符串,需要返回最长回文子串 解法:dp[i][j] 表示 s[i..j] 是否是回文串,转移方程是 dp[i][j] = 1 (if dp[i+1][j-1] = 1 && s[i] == s[j]),初始化条件是 if (s[i] == s[j] && (i == j

【LeetCode】位运算 bit manipulation(共32题)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [78]Subsets [136]Single Number [137]Single Number II [169]Majority Element [187]Repeated DNA Sequences [190]Reverse Bits [191]Number of 1 Bits [201]Bitwise AND of Numbers Range [231]Pow

【HackerRank】 The Full Counting Sort

In this challenge you need to print the data that accompanies each integer in a list. In addition, if two strings have the same integers, you need to print the strings in their original order. Hence, your sorting algorithm should be stable, i.e. the

UVALive 6602 Counting Lattice Squares 【几何】【机智】

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4613 题目大意:给你一个n*m的矩阵格子,在这n*m的矩阵格子中要你选出四个点,形成一个正方形,让正方形的面积为奇数,问可以形成多少个这样的正方形. 题目思路:从每一个奇数开始作为一个基本单元. 面积     边 能组成的正方形: 1*1      1      

【题解】晋升者计数 Promotion Counting [USACO 17 JAN] [P3605]

[题解]晋升者计数 Promotion Counting [USACO 17 JAN] [P3605] 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训.!牛是可怕的管理者! [题目描述] 奶牛从 \(1\) ~ \(N(1≤N≤1e5)\) 进行了编号,把公司组织成一棵树,\(1\)号奶牛作为总裁(树的根节点).除总裁以外的每头奶牛都有且仅有唯一的一个的上司(即它在树上的父结点).每一头牛\(i\)都有一个不同的能力指数 \(p(i)\),描述了她对其工作的擅长程度.如果奶牛

【树状数组+dp+离散化】Counting Sequences

https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/G [题意] 给定一个数组a,问这个数组有多少个子序列,满足子序列中任意两个相邻数的差(绝对值)都不大于d. [思路] 首先,朴素的dp思想: dp[i]为以a[i]结尾的子问题的答案,则dp[i]=sum(dp[k]),k<i&&|a[k]-a[i]|<=d 但是时间复杂度为O(n^2),会超时. 我们可以这样想: 如果数组a排好序后,dp[i]就是区间(a[