离散化+线段树简单例题
POJ 2528
求没有被完全覆盖的海报(不知道是不是这个意思)有多少张。注意题目一开始给的数字不是线段的端点而是线段。所以离散化的时候需要先处理,也就是把右端点+1.然后离散化,插入的时候应该插入线段,所以应该插入(left, right-1)。然后查询只需查询一次,标记即可。
ZOJ 2301, HDU 1199
做法是一样的,都是一维线段树,比较好处理。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <cmath> #include <ctime> #include <set> #include <map> #include <stack> #include <queue> #include <string> #include <bitset> #include <vector> #include <deque> #include <utility> #include <list> #include <sstream> #include <iostream> #include <fstream> #include <functional> #include <numeric> #include <algorithm> using namespace std; //TEMPLATE_BY_LIKE #define EP 1E-10 #define CLR(arr, v) memset(arr, v, sizeof(arr)) #define SQ(a) ((a)*(a)) #define DEBUG(a) printf("%s = %s\n", #a, toStr(a).c_str()) #define FOR(i,s,e) for( int (i)=(s); (i) < (e) ; i++) #define SIZE(X) ((int)(X.size())) #define LENGTH(X) ((int)(X.length())) #define two(X) (1<<(X)) #define twoL(X) (((int64)(1))<<(X)) typedef long long LL; typedef unsigned long long uLL; const double PI = acos(-1.0); int toInt(string s) {int r=0; istringstream sin(s); sin>>r; return r;} LL toInt64(string s) {LL r=0; istringstream sin(s); sin>>r; return r;} double toDouble(string s){double r=0; istringstream sin(s); sin>>r; return r;} double dist(double x1, double y1, double x2, double y2){return sqrt(SQ(x1-x2)+SQ(y1-y2));} bool isUpperCase(char c){return c >= 'A' && c <= 'Z';} bool isLowerCase(char c){return c >= 'a' && c <= 'z';} bool isLetter(char c) {return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z';} bool isDigit(char c) {return c >= '0' && c <= '9';} char toLowerCase(char c){return (isUpperCase(c))?(c + 32) : c;} char toUpperCase(char c){return (isLowerCase(c))?(c - 32) : c;} template<class T> inline T strTo(string s){istringstream is(s);T v;is>>v;return v;} template<class T> inline string toStr(const T& v){ostringstream os;os<<v;return os.str();} template<class T> inline int cMin(T& a, const T& b){return b<a?a=b,1:0;} template<class T> inline int cMax(T& a, const T& b){return a<b?a=b,1:0;} template<class T> inline int cBit(T n){return n?cBit(n&(n-1))+1:0;} template<class T> inline T lowbit(T n){return (n^(n-1))&n;} template<class T> inline T GCD(T a, T b) {if(a<0)return GCD(-a,b);if(b<0)return GCD(a,-b);return (b==0)?a:GCD(b,a%b);} template<class T> inline T LCM(T a, T b) {if(a<0)return LCM(-a,b);if(b<0)return LCM(a,-b);return a*(b/gcd(a,b));} //TEMPLATE_BY_LIKE struct TNode{ int l, r; int color; bool cover; TNode *left, *right; }; TNode tree[50000]; int ncount; void buildTree(TNode *root, int l, int r){ root->l = l; root->r = r; root->cover = true; root->color = 1; if (l != r){ ncount++; root->left = tree + ncount; ncount++; root->right = tree + ncount; buildTree(root->left, l, (l + r) / 2); buildTree(root->right, (l + r) / 2 + 1, r); } } void insert(TNode *root, int l, int r, int col){ if (root->cover && root->color == col) return; if (root->l == l && root->r == r){ root->cover = true; root->color = col; return; } if (root->cover){ root->cover = false; root->left->cover = true; root->right->cover = true; root->left->color = root->color; root->right->color = root->color; } if (root->r != root->l){ int mid = (root->l + root->r) / 2; if (mid < l) insert(root->right, l, r, col); else if (mid >= r) insert(root->left, l, r, col); else { insert(root->left, l, mid, col); insert(root->right, mid + 1, r, col); } } } bool vis[5000]; void query(TNode *root, int l, int r){ if (root->cover){ if (root->color == 2){ for (int i = root->l; i <= root->r; i++) vis[i] = true; } return; } if (root->l - root->r){ int mid = (root->l + root->r) / 2; if (mid < l) query(root->right, l, r); else if (mid >= r) query(root->left, l, r); else { query(root->left, l, mid); query(root->right, mid + 1, r); } } } map<int, int> ma; struct node{ int start, end, col; }; node d[2100]; int p[5000], q[5000]; int main() { int n; while (~scanf("%d", &n)){ int t = 0; ma.clear(); for (int i = 0; i < n; i++) { char c[3]; scanf("%d%d%s", &d[i].start, &d[i].end, c); d[i].end++; if (d[i].start > d[i].end){ int t = d[i].start; d[i].start = d[i].end; d[i].end = t; } if (c[0] == 'w'){ d[i].col = 2; }else d[i].col = 1; p[t++] = d[i].start; p[t++] = d[i].end; } sort(p, p + t); int k = 0; ma[p[0]] = ++k; q[k] = p[0]; for (int i = 1; i < t; i++) if (p[i] != p[i - 1]) { ma[p[i]] = ++k; q[k] = p[i]; } ncount = 0; buildTree(tree, 1, k); for (int i = 0; i < n; i++) { int a = ma[d[i].start], b = ma[d[i].end]; insert(tree, a, b - 1, d[i].col); } CLR(vis, 0); query(tree, 1, k); int maxlen = -1, s = 1; int l1 = 0, l2 = 0; bool flag = false; for (int i = 1; i <= k; i++){ if (!vis[i] && vis[i - 1]){ if (maxlen < q[i] - 1 - q[s]){ maxlen = q[i] - 1 - q[s]; l1 = q[s]; l2 = q[i] - 1; flag = true; } } if (vis[i] && !vis[i - 1]) s = i; } if (maxlen < q[k] - q[s] && vis[k]){ l1 = q[s]; l2 = q[k]; flag = true; } if(!flag)printf("Oh, my god\n"); else printf("%d %d\n", l1, l2); } return 0; }