题目大意:给出一些海报和贴在墙上的区间,问这些海报按照顺序贴完之后,最后能后看到多少种海报。
思路:区间的范围太大,然而最多只会有10000张海报,所以要离散化。之后用线段树随便搞搞就能过。
关键是离散化的方法,这个题我时隔半年才A掉,之前一直就TTT,我还以为是线段树写挂了。当我认为我自己的水平这种水线段树已经基本写不挂的时候又写了这个题,居然还是T。后来我对比别人的代码,才发现是我的离散化写渣了。下面附AC代码(79ms),这个离散化写的比较优雅,时间也很快,以后就这么写了。
CODE(POJ 79ms):
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 100010 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; pair<int,int> interval[MAX]; pair<int,int *> src[MAX << 1]; int cases; int tree[MAX << 2]; int intervals; int cnt,t; bool color[MAX]; inline void Initialize() { t = cnt = 0; memset(color,false,sizeof(color)); memset(tree,0,sizeof(tree)); } inline void PushDown(int pos) { if(tree[pos]) { tree[LEFT] = tree[pos]; tree[RIGHT] = tree[pos]; tree[pos] = 0; } } inline void Modify(int l,int r,int x,int y,int pos,int c) { if(l == x && y == r) { tree[pos] = c; return ; } PushDown(pos); int mid = (l + r) >> 1; if(y <= mid) Modify(l,mid,x,y,LEFT,c); else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c); else { Modify(l,mid,x,mid,LEFT,c); Modify(mid + 1,r,mid + 1,y,RIGHT,c); } } void GetAns(int l,int r,int pos) { if(tree[pos]) { color[tree[pos]] = true; return ; } if(l == r) return ; int mid = (l + r) >> 1; GetAns(l,mid,LEFT); GetAns(mid + 1,r,RIGHT); } int main() { for(cin >> cases; cases; --cases) { scanf("%d",&intervals); Initialize(); for(int i = 1; i <= intervals; ++i) { scanf("%d%d",&interval[i].first,&interval[i].second); src[++cnt] = make_pair(interval[i].first,&interval[i].first); src[++cnt] = make_pair(interval[i].second,&interval[i].second); } sort(src + 1,src + cnt + 1); for(int i = 1; i <= cnt; ++i) { if(src[i].first != src[i - 1].first) ++t; *src[i].second = t; } for(int i = 1; i <= intervals; ++i) Modify(1,cnt,interval[i].first,interval[i].second,1,i); GetAns(1,cnt,1); int ans = 0; for(int i = 1; i <= intervals; ++i) ans += color[i]; printf("%d\n",ans); } return 0; }
CODE(POJ TLE):
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; pair<int,int> interval[MAX]; map<int,int> G; int cases; int tree[MAX << 2]; int intervals,src[MAX << 1]; int cnt,t; bool color[MAX]; inline void Initialize() { G.clear(); t = cnt = 0; memset(color,false,sizeof(color)); memset(tree,0,sizeof(tree)); } inline void PushDown(int pos) { if(tree[pos]) { tree[LEFT] = tree[pos]; tree[RIGHT] = tree[pos]; tree[pos] = 0; } } inline void Modify(int l,int r,int x,int y,int pos,int c) { if(l == x && y == r) { tree[pos] = c; return ; } PushDown(pos); int mid = (l + r) >> 1; if(y <= mid) Modify(l,mid,x,y,LEFT,c); else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c); else { Modify(l,mid,x,mid,LEFT,c); Modify(mid + 1,r,mid + 1,y,RIGHT,c); } } void GetAns(int l,int r,int pos) { if(tree[pos]) { color[tree[pos]] = true; return ; } if(l == r) return ; int mid = (l + r) >> 1; GetAns(l,mid,LEFT); GetAns(mid + 1,r,RIGHT); } int main() { for(cin >> cases; cases; --cases) { scanf("%d",&intervals); Initialize(); for(int i = 1; i <= intervals; ++i) { scanf("%d%d",&interval[i].first,&interval[i].second); src[++cnt] = interval[i].first; src[++cnt] = interval[i].second; } sort(src + 1,src + cnt + 1); G[src[1]] = ++t; for(int i = 2; i <= cnt; ++i) if(src[i] != src[i - 1]) G[src[i]] = ++t; for(int i = 1; i <= intervals; ++i) Modify(1,cnt,G[interval[i].first],G[interval[i].second],1,i); GetAns(1,cnt,1); int ans = 0; for(int i = 1; i <= intervals; ++i) ans += color[i]; printf("%d\n",ans); } return 0; }
CODE(POJ 344ms):
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; pair<int,int> interval[MAX]; map<int,int> *G; int cases; int tree[MAX << 2]; int intervals,src[MAX << 1]; int cnt,t; bool color[MAX]; inline void Initialize() { G = new map<int,int>; t = cnt = 0; memset(color,false,sizeof(color)); memset(tree,0,sizeof(tree)); } inline void PushDown(int pos) { if(tree[pos]) { tree[LEFT] = tree[pos]; tree[RIGHT] = tree[pos]; tree[pos] = 0; } } inline void Modify(int l,int r,int x,int y,int pos,int c) { if(l == x && y == r) { tree[pos] = c; return ; } PushDown(pos); int mid = (l + r) >> 1; if(y <= mid) Modify(l,mid,x,y,LEFT,c); else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c); else { Modify(l,mid,x,mid,LEFT,c); Modify(mid + 1,r,mid + 1,y,RIGHT,c); } } void GetAns(int l,int r,int pos) { if(tree[pos]) { color[tree[pos]] = true; return ; } if(l == r) return ; int mid = (l + r) >> 1; GetAns(l,mid,LEFT); GetAns(mid + 1,r,RIGHT); } int main() { for(cin >> cases; cases; --cases) { scanf("%d",&intervals); Initialize(); for(int i = 1; i <= intervals; ++i) { scanf("%d%d",&interval[i].first,&interval[i].second); src[++cnt] = interval[i].first; src[++cnt] = interval[i].second; } sort(src + 1,src + cnt + 1); (*G)[src[1]] = ++t; for(int i = 2; i <= cnt; ++i) if(src[i] != src[i - 1]) (*G)[src[i]] = ++t; for(int i = 1; i <= intervals; ++i) Modify(1,cnt,(*G)[interval[i].first],(*G)[interval[i].second],1,i); GetAns(1,cnt,1); int ans = 0; for(int i = 1; i <= intervals; ++i) ans += color[i]; printf("%d\n",ans); } return 0; }