牛客 20951 网络优化
题目链接 :网络优化
题目意思:
题目给出一个1....n的序列,第一行输入n和m,在下面的m行,每一行有三个数字分别是li,ri,vi,代表着第i条网线对用户li 到 ri 有用,且最多只有vi个人相连接。问最多可以有多少人可以同时连接。
题目分析:
有题目可知,有的点可能被覆盖好几次,也可能一次都不行,一开始我是想要将每个点可以被多少个网线覆盖,在从小到大排序,但是不行,我也不知道为什么不行。后面知道另一种写法,就是现在要讲的。可以将n个点遍历一遍,在这之前我们将m条网线拍个序,按照l来排序,如果l相等的话,就先将长度更小的放在前面,长度更大的放在后面。然后进行遍历,从1到n,在这个过程中就可以将l == i的网线放进优先队列里,可以放进去的网线肯定可以为i点服务的,然后将不满足条件的网线弹出来,比如长度减为0了,或者r < i,这两种肯定是不行的,所以就可以弹出来了,此时如果优先队列里面还有网线的话,那肯定可以为i点服务的。
大概的就这样了,优先队列里是按照r的大小进行排序的,详细看代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 typedef long long ll; 7 const int ma = 1e4 + 7; 8 int n,m; 9 struct node 10 { 11 int l,r,len; 12 bool operator< (const node& a) const 13 { 14 if(l == a.l && r == a.r) return len < a.len; 15 else if(l == a.l) return r < a.r; 16 else 17 { 18 return l < a.l; 19 } 20 } 21 } num[ma]; 22 23 struct tr 24 { 25 int rest,r; 26 bool operator< (const tr& a) const 27 { 28 if(r == a.r) return rest < a.rest; 29 else return r > a.r; 30 } 31 }; 32 33 int main() 34 { 35 while(scanf("%d%d",&n,&m) != EOF) 36 { 37 for(int i = 1; i <= m; i++) 38 { 39 scanf("%d%d%d",&num[i].l,&num[i].r,&num[i].len); 40 }// 用结构体存储网线, 41 sort(num+1,num+1+m); 42 //网线拍寻 43 int cnt(1),ans(0); 44 // cnt 控制下标 45 priority_queue<tr> q; 46 tr a; 47 for(int i = 1; i <= n; i++) 48 { 49 while(num[cnt].l == i) 50 { 51 q.push({num[cnt].len,num[cnt].r}); 52 cnt++; 53 //将l == i 的网线放进队列里,并且进行排序,这样就会先将r更小的放在队首,这样就可以在下面进行刷选 54 } 55 while(!q.empty() && (!q.top().rest || q.top().r < i)) 56 q.pop();//刷选,将没用的弹掉,以保证后面的数据有效。 57 if(q.empty()) continue;//如果此时队列不为空,也就是讲此时队列里的都是有效的, 58 ans++;//所以ans就可以+1了 59 a = q.top(),q.pop(); 60 a.rest--,q.push(a); 61 } 62 cout<<ans<<endl; 63 } 64 return 0; 65 }
写完之后还是太菜了,唉