题目链接:ヽ(ˋ▽ˊ)ノ
哎~网上看了老久,才知道怎么离散化,郁闷,建树前需要离散化点, 用p[i][2]来存储每个点离散化前的信息, 用结构体num来存储每个点的具体信息
code:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int num, id , left;//该点的数值, 为哪条线段的, 左端点还是右端点 }node; node num[2*20005]; struct Tnode { int left, right, color; }tree[4*20005]; int p[10005][2], sum = 0, flag[20005]; int cmp( const void *a ,const void *b) { return (*(node *)a).num>(*(node *)b).num?1:-1; } void build(int root, int left, int right) { int mid = (left+right)/2; if(left == right) { tree[root].left = tree[root].right = left; tree[root].color = 0; return ; } tree[root].left = left; tree[root].right = right; tree[root].color = 0; build(2*root, left, mid); build(2*root+1, mid+1, right); } void insert(int root, int left, int right, int color) { int mid = (tree[root].left+tree[root].right)/2; if(tree[root].left == left && tree[root].right == right) { tree[root].color = color; return ; } if(tree[root].color) { tree[2*root].color = tree[root].color; tree[2*root+1].color = tree[root].color; tree[root].color = 0; } if(right<=mid) insert(2*root, left, right, color); else if(left>mid) insert(2*root+1, left, right, color); else { insert(2*root, left, mid, color); insert(2*root+1, mid+1, right, color); } } void query(int root) { if(tree[root].color) { if(!flag[tree[root].color]) { flag[tree[root].color] = 1; sum++; } return ; } query(2*root); query(2*root+1); } int main() { int i = 0, n = 0, t = 0, k = 0, pre = 0, index = 0; scanf("%d",&t); while(t--) { k = 0; scanf("%d",&n); for(i = 0; i<n; i++) { scanf("%d %d",&p[i][0], &p[i][1]); num[k].num = p[i][0];//用num来存储该点的信息有为第几段, 端点位, 数值 num[k].id = i; num[k++].left = 1; num[k].num = p[i][1]; num[k].id = i; num[k++].left = 0; } qsort(num, k, sizeof(num[0]), cmp);//对结构体中的数值排序 pre = -1; index = 0;//用index来确定离散化后的范围 for(i = 0; i<2*n; i++) { if(num[i].num != pre)//不是重复的点范围加一 { index++; pre = num[i].num; } if(num[i].left) p[num[i].id][0] = index; else p[num[i].id][1] = index; }//离散化完毕 build(1, 1, index); for(i = 0; i<n; i++) insert(1, p[i][0], p[i][1], i+1);//对线段进行上色 sum = 0; memset(flag, 0, sizeof(flag));//判重 query(1); printf("%d\n",sum); } return 0; }
code:简单点的离散化
离散化时注意相邻两点的离散化
数据
1 10
1 3
6 10
不能离散化成4个点, 要离散化为5个点, 应为3与6在没离散化前是图了色的, 离散化完后不能忽略了这个区间
#include <stdio.h> #include <stdlib.h> #include <string.h> int sum = 0, p[10005][2], num[20005], num1[100005], tree[50005*6], used[100005]; int cmp(const void *a, const void *b) { return *(int *)a-*(int *)b; } void build(int root, int left, int right) { int mid = (left+right)/2; if(left == right) { tree[root] = 0; return; } tree[root] = 0; build(2*root, left, mid); build(2*root+1, mid+1, right); } void insert(int root, int left, int right, int start, int end, int col) { int mid = (left+right)/2; if(num1[left] >= start && num1[right] <= end) { tree[root] = col; return ; } if(tree[root] != 0) { tree[2*root] = tree[2*root+1] = tree[root]; tree[root] = 0; } if(num1[mid]>=start) insert(2*root, left, mid, start, end, col); if(num1[mid]<end) insert(2*root+1, mid+1, right, start, end, col); } void query(int root, int left, int right) { int col = tree[root], mid = (left+right)/2; if(col != 0) { if(!used[col]) { used[col] = 1; sum++; } return ; } if(left == right) return; query(2*root, left, mid); query(2*root+1, mid+1, right); } int main() { int t = 0, i = 0, n = 0, k = 0, index = 0, pre = -1; scanf("%d",&t); while(t--) { scanf("%d",&n); k = 1; for(i = 0; i<n; i++) { scanf("%d %d",&p[i][0], &p[i][1]); num[k++] = p[i][0]; num[k++] = p[i][1]; } num[0] = 0; qsort(num, k, sizeof(num[0]), cmp); pre = -1; index = 1; num[0] = num[1]; for(i = 1; i<k; i++) { if(num[i]-num[i-1]>1) num1[index++] = num[i]-1; if(num[i] != pre) { num1[index++] = num[i]; pre = num[i]; } } build(1, 1, index-1); //memset(tree, 0, 6*index*sizeof(tree[0])); memset(used,0,sizeof(used)); for(i = 0; i<n; i++) insert(1, 1, index-1, p[i][0], p[i][1], i+1); sum = 0; query(1, 1, index-1); printf("%d\n",sum); } return 0; }
这代码错的也能过...........
#include <stdio.h> #include <string.h> #include <algorithm> #define N 20002 using namespace std; struct node { int x, y; }p[N]; int cnt = 0, ans = 0, id = 0, X[2*N], t[3*N], used[N]; void update(int c, int l, int r, int lf, int rt, int col) { int m = l+(r-l)/2; if(lf<=X[l] && rt>=X[r]) { t[c] = col; return ; } if(t[c]) { t[2*c] = t[2*c+1] = t[c]; t[c] = 0; } if(lf<=X[m]) update(2*c, l, m, lf, rt, col); if(rt>X[m]) update(2*c+1, m+1, r, lf, rt, col); } void query(int c, int l, int r) { int m = l+(r-l)/2; if(t[c] && !used[t[c]]) { ans++; used[t[c]] = 1; } if(t[c]) return ; if(l == r) return ; query(2*c, l, m); query(2*c+1, m+1, r); } int main() { //freopen("input.txt", "r", stdin); int i = 0, c = 0, n = 0; scanf("%d", &c); while(c--) { memset(used, 0, sizeof(used)); memset(t, 0, sizeof(t)); cnt = ans = 0; scanf("%d", &n); for(i = 0; i<n; i++) { scanf("%d %d", &p[i].x, &p[i].y); X[cnt++] = p[i].x; X[cnt++] = p[i].y; } sort(X, X+cnt); cnt = unique(X, X+cnt)-X; for(i = 0; i<n; i++) update(1, 0, cnt-1, p[i].x, p[i].y, i+1); query(1, 0, cnt-1); printf("%d\n", ans); } return 0; }