这是经典的线段树染色问题。用到了区间改值。
这个题的难点在于离散化。普通的离散化是不行的。因为在线段树和这个题中数字代表的是一段区间,这样4和5是相邻的。而且普通的离散化每个数都是相邻的。如果有两个区间
【1,6】,【10,20】,【1,20】。离散化以后就变成【1,2】【3,4】,【1,4】。很明显两个答案并不一样。这样,如果相邻两个点的差值大于1,则离散化的时候编号多加一。
POJ的disscuss上说这题数据有问题。我也不知道是否是真的。我下面的代码在POJ上WA了。
在http://acm.nyist.net/JudgeOnline/problem.php?pid=9上面AC了。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <cmath> #include <stack> #include <queue> #include <set> #include <map> #include <algorithm> #define ll long long #define INF 2139062143 #define inf -2139062144 #define MOD 20071027 #define MAXN 100005 #define LEN 222222<<2 using namespace std; set<int> cnt; struct Line_Tree { private: int setv[LEN]; int sv,ql,qr,sz; void PushDown(int o) { if(setv[o]) { setv[o<<1|1]=setv[o<<1]=setv[o]; setv[o]=0; } } void myupdate(int o,int L,int R) { if(ql<=L&&R<=qr) { setv[o]=sv; return ; } PushDown(o); int M=(L+R)>>1; if(ql<=M) myupdate(o<<1,L,M); if(M<qr) myupdate(o<<1|1,M+1,R); } void myquery(int o,int L,int R) { if(L==R) { cnt.insert(setv[o]); return ; } PushDown(o); int M=(L+R)>>1; if(ql<=M) myquery(o<<1,L,M); if(M<qr) myquery(o<<1|1,M+1,R); } public: void init(int n) { sz=n; } void clear(int o,int L,int R) { setv[o]=0; if(L==R) return ; int M=(L+R)>>1; clear(o<<1,L,M); clear(o<<1|1,M+1,R); } void update(int v,int L,int R) { sv=v; ql=L; qr=R; myupdate(1,1,sz); } int solve() { cnt.clear(); ql=1; qr=sz; myquery(1,1,sz); return cnt.size(); } }; Line_Tree tree; map<int,int> has; int s; int ID(int val) { if(!has[val]) return has[val]=++s; return has[val]; } vector<int> arr; vector<pair <int,int> > vec; int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); has.clear(); arr.clear(); vec.clear(); for(int i=0; i<n; ++i) { int x,y; scanf("%d%d",&x,&y); vec.push_back(pair<int,int>(x,y)); arr.push_back(x); arr.push_back(y); } sort(arr.begin(),arr.end()); s=0; for(int i=0; i<arr.size(); ++i) { if(i&&arr[i]==arr[i-1] ) continue; if(i&&arr[i]-arr[i-1]>1) s++; ID(arr[i]); } tree.init(s); tree.clear(1,1,s); for(int i=0; i<vec.size(); ++i) tree.update(i+1,has[vec[i].first],has[vec[i].second]); printf("%d\n",tree.solve()); } return 0; }