首先左边的是必须要选的,然后右边的需要注意,有些区间是可以舍掉的。1、区间里有两个不同的A。 2、区间里有一个A,而且这个A不是这个区间对应的A。
这个题我一开始错在了第2个判定条件上,我定义的id记录的是最后一个出现位置,不能进行判断,所以干脆在结构体里记录了他对应的A值。
舍掉后留下的区间,可以按照区间左边界排序,然后求交集即可。
总体来说,贪心的思想还是不难的,就是有一些细节需要注意。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<queue> #include<set> #include<map> using namespace std; const int N = 1e5+5; const int M = 1e6+6; set<int>st; set<int>:: iterator it; map<int,int> id; struct Edge { int l,r,A,ok; void Set(int x,int y,int a) { l = x; r = y; A = a; ok = 0; } } e[N]; int sum[M]; bool cmp(Edge a,Edge b) { if(a.l != b.l) return a.l < b.l; return a.r < b.r; } int main() { // freopen("F.in.cpp","r",stdin); int T,n,a,b,c,ans,ca=0,Max,Min,cnt; scanf("%d",&T); while(T--) { scanf("%d",&n); st.clear(); id.clear(); Max = -1; Min = 1e8; for(int i = 1; i <= n; i++) { scanf("%d%d%d",&a,&b,&c); id[a] = i; e[i].Set(b,c,a); st.insert(a); Max = max(max(Max,a),e[i].r); Min = min(min(Min,a),e[i].l); } cnt = 0; for(int i = Min-1; i <= Max; i++) { if(id[i]) cnt++; sum[i] = cnt; } ans = st.size(); // printf("ans1 = %d\n",ans); for(int i = 1; i <= n; i++) { if(sum[e[i].r] - sum[e[i].l-1] == 1) { it = st.lower_bound(e[i].l); if(*it != e[i].A) e[i].ok = 1; } if(sum[e[i].r] - sum[e[i].l-1] > 1) e[i].ok = 1; } sort(e+1,e+n+1,cmp); int tr=-1; for(int i = 1; i <= n; i++) { if(e[i].ok == 1) continue; if(tr == -1 || tr < e[i].l) { tr = e[i].r; ans++; } else if(tr >= e[i].l) { tr = min(e[i].r,tr); } } printf("Case #%d: %d\n",++ca,ans); } return 0; }
UVALive 6911 Double Swords (Set,贪心,求区间交集)
原文:http://www.cnblogs.com/jifahu/p/5988611.html