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