【扫描线或树状数组】CSU 1335 高桥和低桥

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1335

【题意】

  • 给定n座桥的高度,给定m次洪水每次的涨水水位ai和退水水位bi
  • 询问有多少座桥被淹的次数大于等于k
  • 洪水最开始的水位为1

【思路】

  • 每座桥被淹一次是这样的:开始时的水位小于桥的高度,洪水最高点的水位不小于桥的高度,如有一座高度为5的桥,对于数据7 6和7 3被淹的次数都是1(看5在不在(1,7]的区间内)
  • 把n座桥排序,每次洪水都有一个区间的桥被淹,问最后每座桥被淹多少次
  • 这就是裸的扫描线,或者树状数组区间修改单点查询也可以

【AC】

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string>
 5 #include<cstring>
 6 using namespace std;
 7 typedef long long ll;
 8
 9 const int maxn=1e5+2;
10 int a[maxn];
11 int n,m,k;
12 int f[maxn];
13 void init()
14 {
15     memset(f,0,sizeof(f));
16 }
17 int main()
18 {
19     int cas=0;
20     while(~scanf("%d%d%d",&n,&m,&k))
21     {
22         init();
23         for(int i=1;i<=n;i++)
24         {
25             scanf("%d",&a[i]);
26         }
27         sort(a+1,a+n+1);
28         int x,y;
29         int st=1,ed;
30         for(int i=1;i<=m;i++)
31         {
32             scanf("%d%d",&x,&y);
33             ed=x;
34             int pos1=upper_bound(a+1,a+1+n,st)-a;
35             int pos2=upper_bound(a+1,a+1+n,ed)-a-1;
36             f[pos1]++;
37             f[pos2+1]--;
38             st=y;
39         }
40         int ans=0;
41         int s=0;
42         for(int i=1;i<=n;i++)
43         {
44             s+=f[i];
45             if(s>=k) ans++;
46         }
47         printf("Case %d: %d\n",++cas,ans);
48     }
49     return 0;
50 }

扫描线

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string>
 5 #include<cstring>
 6 using namespace std;
 7 typedef long long ll;
 8
 9 const int maxn=1e5+2;
10 int a[maxn];
11 int tree[maxn];
12 int n,m,k;
13 int lowbit(int x)
14 {
15     return x&(-x);
16 }
17 void add(int k,int x)
18 {
19     while(k<=n)
20     {
21         tree[k]+=x;
22         k+=lowbit(k);
23     }
24 }
25 int query(int k)
26 {
27     int res=0;
28     while(k)
29     {
30         res+=tree[k];
31         k-=lowbit(k);
32     }
33     return res;
34 }
35 void init()
36 {
37     memset(tree,0,sizeof(tree));
38 }
39 int main()
40 {
41     int cas=0;
42     while(~scanf("%d%d%d",&n,&m,&k))
43     {
44         init();
45         for(int i=1;i<=n;i++)
46         {
47             scanf("%d",&a[i]);
48         }
49         sort(a+1,a+n+1);
50         int x,y;
51         int st=1,ed;
52         for(int i=1;i<=m;i++)
53         {
54             scanf("%d%d",&x,&y);
55             ed=x;
56             int pos1=upper_bound(a+1,a+1+n,st)-a;
57             int pos2=upper_bound(a+1,a+1+n,ed)-a-1;
58             add(pos1,1);
59             add(pos2+1,-1);
60             st=y;
61         }
62         int ans=0;
63         for(int i=1;i<=n;i++)
64         {
65             if(query(i)>=k)
66             {
67                 ans++;
68             }
69         }
70         printf("Case %d: %d\n",++cas,ans);
71     }
72     return 0;
73 }

树状数组区间修改单点查询

时间: 2024-10-13 10:34:15

【扫描线或树状数组】CSU 1335 高桥和低桥的相关文章

CSU 1335: 高桥和低桥(扫描线) 13年省赛题

1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 957  Solved: 279 [Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一

csu 1335: 高桥和低桥(二分+扫气球)

1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 861  Solved: 248 [Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一

CSU 1335: 高桥和低桥 (二分查找,树状数组)

Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算“淹了两次”.举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一次洪水:水位提高到6(两个桥都被淹),退到2(高桥不再被淹,但低桥仍然被淹) 第二次洪水:水位提高到8(高桥又被淹了),退到3. 没错,文字游戏.关键在于“又”的含义.如果某次洪水退去之后一座桥仍然被淹(即水位不小于桥的

csuoj 1335: 高桥和低桥

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1335 1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 802  Solved: 221[Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低

变化的区间树状数组,单点查询

hdu  1556 Color the ball 要想区间改动的话,那么节点就必须往上更新,查询时往上累加.(区间改动.单点查询) #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=100000+5; int C[maxn]; int n; int lowbit(int x) { return (-x)&x; } void upd

高桥低桥(树状数组离散化)

1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 362  Solved: 62 [Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一次

数据结构之树状数组

树状数组适合单个元素经常修改,而且还要反复求某个区间的和 树状数组的编程效率和程序运行效率都要比线段树要高(时间复杂度一样,但是梳妆数组的常数较小) 如果每次修改的不是一个数,而是一个区间就不适合用树状数组了(效率较低) 树状数组的时间复杂度总结: 建数组0(n) 更新0(logn) 局部求和0(logn) 当想要查询一个SUM(n)(求a[n]的和),可以依据如下算法即可: step1: 令sum = 0,转第二步: step2: 假如n <= 0,算法结束,返回sum值,否则sum = su

树状数组小结

树状数组基本概念 树状数组也是进行区间操作的常用数据结构.树状数组适用于单个元素经常修改,而且还反复求部分的区间和的情况. 对于数组a,构造一个新的数组C,使得C[i] = a[i-2^k+1] + a[i-2^k+2] + ... + a[i]; (1) i >= 1: (2) k为i在二进制表示下末尾的连续的0的个数,2^k = i&(-i),通常用lowbit(i)表示i对应的2^k,lowbit(i) = 2^k = i&(-i): 则数组C为数组a的树状数组. 数组数组的结

TOJ 4602:高桥和低桥(二分或树状数组+二分)

描述 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明:假定高桥和低桥的高度分别是5和2,初始水位为1第一次洪水:水位提高到6(两个桥都被淹),退到2(高桥不再被淹,但低桥仍然被淹)第二次洪水:水位提高到8(高桥又被淹了),退到3.没错,文字游戏.关键在于"又"的含义.如果某次洪水退去之后一座桥仍然被淹(即水位不小于